Introduction
In this project, regression models for three different times series
data will be built. These data are collected from Central Bank of the
Republic of Turkey. the chosen data are:
- Unemployment percentage
- House price index
- Real sector confidence index
All of these data are monthly and we have the time series for them
from 01-2014 to 01-2024. Therefore they can be plotted against
themselves.
The basic approach to the problem is like this: We ask ourselves what
could these forecast variables be related to?
After finding the potential answers, these answers are searched in
Google trends data and downloaded. Also the time series plot is observed
in order to see any trend or seasonality and add them as predictors as
well.
After the predictors are decided on several models are built by using
all of them and removing some of them. then these models are compared
using tests such as AIC or adjusted R squared.
After deciding on which predictors to use, we can proceed with our
final decided model. The final decided model is plotted agains the real
data in order to see how good the model is.
Finally, the residuals are evaluated. In this part, we try to answer
whether our assumptions about the residuals are correct. These are:
- They have mean zero
- Distributed approximately normal
- They don’t have autocorrelation
If all three of these apply then we can conclude that we have a
decent model.
Firstly require the necessary libraries and set the plot window,
height and width.
require(data.table)
Loading required package: data.table
Registered S3 method overwritten by 'data.table':
method from
print.data.table
data.table 1.15.2 using 1 threads (see ?getDTthreads). Latest news: r-datatable.com
**********
This installation of data.table has not detected OpenMP support. It should still work but in single-threaded mode.
This is a Mac. Please read https://mac.r-project.org/openmp/. Please engage with Apple and ask them for support. Check r-datatable.com for updates, and our Mac instructions here: https://github.com/Rdatatable/data.table/wiki/Installation. After several years of many reports of installation problems on Mac, it's time to gingerly point out that there have been no similar problems on Windows or Linux.
**********
require(lubridate)
Loading required package: lubridate
Attaching package: ‘lubridate’
The following objects are masked from ‘package:data.table’:
hour, isoweek, mday, minute, month, quarter, second, wday, week, yday, year
The following objects are masked from ‘package:base’:
date, intersect, setdiff, union
require(forecast)
Loading required package: forecast
require(skimr)
Loading required package: skimr
Registered S3 methods overwritten by 'htmltools':
method from
print.html tools:rstudio
print.shiny.tag tools:rstudio
print.shiny.tag.list tools:rstudio
require(repr)
Loading required package: repr
require(readxl)
Loading required package: readxl
require(ggplot2)
Loading required package: ggplot2
Want to understand how all the pieces fit together? Read R for Data Science:
https://r4ds.hadley.nz/
options(repr.plot.width=12.7, repr.plot.height=8.5)
Create data tables for our three forecast variables.
data_path_unemployment ='/Users/ahmetkarakose/Desktop/EVDS.xlsx'
unemployment_data = read_excel(data_path)
New names:
data_path_housing = '/Users/ahmetkarakose/Desktop/konut_fiyat.xlsx'
house_index_data = read_excel(data_path_housing)
New names:
data_path_confidence = '/Users/ahmetkarakose/Desktop/confidence.xlsx'
confidence = read_excel(data_path_confidence)
New names:
Manipulate and clean the data, so it’s at a desired format. Make the
forecast values as type numeric. Rename the forecast variable column to
a more readable title and make the date column as date type.
Also, create a combined version of these three data.
unemployment_data <- unemployment_data[-(122:133),]
unemployment_data <- unemployment_data[,-3]
unemployment_data$"TP YISGUCU2 G8" <- as.numeric(unemployment_data$"TP YISGUCU2 G8")
names(unemployment_data)[names(unemployment_data) == "TP YISGUCU2 G8"] <- "Unemployment"
unemployment_data$Date <- paste(unemployment_data$Date, "-01", sep = "")
unemployment_data$Date <- as.Date(unemployment_data$Date)
house_index_data <- house_index_data[-(122:133),]
house_index_data <- house_index_data[,-3]
house_index_data$"TP HKFE01" <- as.numeric(house_index_data$"TP HKFE01")
names(house_index_data)[names(house_index_data) == "TP HKFE01"] <- "House Price Index"
house_index_data$Tarih <- paste(house_index_data$Tarih, "-01", sep = "")
house_index_data$Tarih <- as.Date(house_index_data$Tarih)
confidence <- confidence[-(122:133),]
confidence <- confidence[,-3]
confidence$"TP GY1 N2" <- as.numeric(confidence$"TP GY1 N2")
names(confidence)[names(confidence) == "TP GY1 N2"] <- "Real Sector Confidence Index"
confidence$Date <- paste(confidence$Date, "-01", sep = "")
confidence$Date <- as.Date(confidence$Date)
combined <- cbind(unemployment_data[,2], house_index_data[,2], confidence[,2])
combined
In order to see the correlation between data, plot each forecast
variable agains the other one and see their correlation values. They
need to be less than 0.5 in order to proceed with these forecast
varaibles.
As it can be seen below the correlations are:
- -0.398 for House Price Index vs. Unemployment
- -0.310 for Real Sector Confidence vs. Unemployment
- -0.010 for Real Sector Confidence vs. House Price Index
require(GGally)
Loading required package: GGally
Registered S3 method overwritten by 'GGally':
method from
+.gg ggplot2
ggpairs(combined)

Unemployment
Firstly, the regression model for the Unemployment data will be
built.
Below is the Unemployment vs. Time graph. We can make some deductions
out of it:
- There is an obvious seasonality between 2014 - 2018 and 2021-2024.
So seasonality can be added to our model.
- Also there is increasing trend between 2014-2018 and decreasing
trend between 2021-2024. A piecewise trend could be added to our
model.
- There is a sharp increase in 2019.
time_data <- c(year(min(unemployment_data$Date)), month(min(unemployment_data$Date)))
unemployment_ts <- ts(unemployment_data$Unemployment, start = time_data, frequency = 12)
autoplot(unemployment_ts) + ggtitle("Unemployment (%) vs Time") + xlab("Year") + ylab("Unemployment (%)")

When we observe the ACF function for the time series we can observe
an increase in lag-12 and lag-24. This proves there is seasonality in
data.
ggAcf(unemployment_ts, lag.max = 48) + ggtitle("Unemployment ACF")

Now, we want to find predictors from Google Trends that can be
somehow related with the Unemployment in Turkey. When keywords for this
relation is thought for, these keywords are found to be logical and
related with Unemployment:
- “Kredi”: Maybe people are seeking for more credits when unemployment
increases
- “İş ilanı”: People may be seeking more jobs when unemployment
increases.
- “İşsizlik”: Obviously people will search this term when unemployment
increases
- “Mülakat”: Maybe people are seeking for more interviews because they
want to enter new jobs.
It should be noted that maybe the lagged values of these data can be
better predictors because, people would search these terms after
Unemployment increases. These search terms are results, so the affects
of these search terms may be delayed.
Below all of the data is gathered and time series objects are formed.
All potential predictor data are plotted and a combination of the
potentil predictors are combined. These predictors are also combined
within another dataframe.
kredi = fread("/Users/ahmetkarakose/Desktop/kredi.csv")
names(kredi)[names(kredi) == "kredi: (Türkiye)"] <- "Kredi"
kredi_ts <- ts(credit_data[,-1], start = time_data, frequency = 12)
is_ilani = fread("/Users/ahmetkarakose/Desktop/is_ilani.csv")
names(is_ilani)[names(is_ilani) == "iş ilanı: (Türkiye)"] <- "İş ilanı"
is_ilani_ts <- ts(is_ilani[,-1], start = time_data, frequency = 12)
issizlik = fread("/Users/ahmetkarakose/Desktop/issizlik.csv")
names(issizlik)[names(issizlik) == "işsizlik: (Türkiye)"] <- "İşsizlik"
issizlik_ts <- ts(issizlik[,-1], start = time_data, frequency = 12)
mulakat = fread("/Users/ahmetkarakose/Desktop/mulakat.csv")
names(mulakat)[names(mulakat) == "mülakat: (Türkiye)"] <- "Mülakat"
mulakat_ts <- ts(interview_data[,-1], start = time_data, frequency = 12)
autoplot(kredi_ts)

autoplot(is_ilani_ts)

autoplot(issizlik_ts)

autoplot(mulakat_ts)

predictors_unemployment <- cbind(kredi[,-1], is_ilani[,-1], issizlik[,-1], mulakat[,-1])
df_unemployment <- cbind(unemployment_data, predictors)
Below is the correlations between each predictors and the forecast
variable. The relations of each of them can be observed below.
require(GGally)
ggpairs(df[,-1])

Now, it’s time to create the model. Firstly the lagged dataframes for
all of the selected predictors are created (google trends data). This is
to compare the lagged models without the lagged model. Then the
piecewise linear trend is formed. In the model seasonal dummy variables
are also added. Three possible models are created:
- fit: Using all the predictors
- fit.lag1: Using all the lag-1 predictors
- fit.lag2: Using all the lag-2 predictors
The best one will be evaluated based on the lowest AIC value. As it
can be seen below, the lowest AIC value is the one with no_lag. We will
proceed with this model in the upcoming comparisons.
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:data.table’:
between, first, last
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
kredi_lag <- mutate(kredi,
kredi_lag1 = lag(kredi$Kredi, 1), # Lag 1
kredi_lag2 = lag(kredi$Kredi, 2), # Lag 2
)
is_ilani_lag <- mutate(is_ilani,
is_ilani_lag1 = lag(is_ilani$"İş ilanı", 1), # Lag 1
is_ilani_lag2 = lag(is_ilani$"İş ilanı", 2), # Lag 2
)
issizlik_lag <- mutate(issizlik,
issizlik_lag1 = lag(issizlik$"İşsizlik", 1), # Lag 1
issizlik_lag2 = lag(issizlik$"İşsizlik", 2), # Lag 2
)
mulakat_lag <- mutate(mulakat,
mulakat_lag1 = lag(mulakat$"Mülakat", 1), # Lag 1
mulakat_lag2 = lag(mulakat$"Mülakat", 2), # Lag 2
)
combined_lag <- cbind(kredi_lag, is_ilani_lag, issizlik_lag, mulakat_lag)
t <- time(unemployment_ts)
t.break1 <- 2018
t.break2 <- 2021
tb1 <- ts(pmax(0, t - t.break1), start = 2014, end = 2024, frequency = 12)
tb2 <- ts(pmax(0, t- t.break2), start = 2014, end = 2024, frequency = 12)
fit <- tslm(unemployment_ts ~ t +
tb1 +
tb2 +
seasonaldummy(unemployment_ts) +
kredi_ts +
is_ilani_ts +
issizlik_ts +
mulakat_ts)
fit.lag1 <- tslm(unemployment_ts ~ t +
tb1 +
tb2 +
seasonaldummy(unemployment_ts) +
kredi_lag1 +
is_ilani_lag1 +
issizlik_lag1 +
mulakat_lag1, data = combined_lag)
fit.lag2 <- tslm(unemployment_ts ~ t +
tb1 +
tb2 +
seasonaldummy(unemployment_ts) +
kredi_lag2 +
is_ilani_lag2 +
issizlik_lag2 +
mulakat_lag2, data = combined_lag)
no_lag <- CV(fit)
lag_1 <- CV(fit.lag1)
lag_2 <- CV(fit.lag2)
CV_data <- data.frame(rbind(no_lag, lag_1, lag_2))
CV_data
Now, we will inspect the model further and try to remove the
unnecessary predictor. In this case all of the predictors (google trends
data) are removed one by one and the models are compared according to
AIC values. The lowes AIC value model is: fit.w.o.mulakat. This is the
model that doesn’t contain the keyword “Mülakat”. So our final model is
chosen and the residual analysis will be proceeded accordingly.
fit.everything <- tslm(unemployment_ts ~ t +
tb1 +
tb2 +
seasonaldummy(unemployment_ts) +
kredi_ts +
is_ilani_ts +
issizlik_ts +
mulakat_ts)
fit.w.o.kredi <- tslm(unemployment_ts ~ t +
tb1 +
tb2 +
seasonaldummy(unemployment_ts) +
is_ilani_ts +
issizlik_ts +
mulakat_ts)
fit.w.o.is_ilani <- tslm(unemployment_ts ~ t +
tb1 +
tb2 +
seasonaldummy(unemployment_ts) +
kredi_ts +
issizlik_ts +
mulakat_ts)
fit.w.o.issizlik <- tslm(unemployment_ts ~ t +
tb1 +
tb2 +
seasonaldummy(unemployment_ts) +
kredi_ts +
is_ilani_ts +
mulakat_ts)
fit.w.o.mulakat <- tslm(unemployment_ts ~ t +
tb1 +
tb2 +
seasonaldummy(unemployment_ts) +
kredi_ts +
is_ilani_ts +
issizlik_ts)
all <- CV(fit.everything)
no_kredi <- CV(fit.w.o.kredi)
no_is_ilani <- CV(fit.w.o.is_ilani)
no_issizlik <- CV(fit.w.o.issizlik)
no_mulakat <- CV(fit.w.o.mulakat)
CV_data <- data.frame(rbind(all, no_kredi, no_is_ilani, nos_issizlik, no_mulakat))
CV_data
The model and the data are plotted in order to see visually how they
behave.
autoplot(unemployment_ts, series = "Data") +
autolayer(fitted(fit.w.o.mulakat), series = "Model")

From the residual analysis part we can conclude that:
- The residuals seem to have mean zero and them seem to be normally
distributed.
- However they show increasing AC especially at lags 12,24 and 36.
Therefore we can deduct that there is more information left out
especially in seasonality terms.
When considering different predictors we can observe that January,
February and March seasonal variables are actually not very intuitive as
they have high p-values.
When the Residuals vs. Fitted values graph is observed, it can be
seen that
Overall, the model seems to be adequate, however there are parts to
improve the model, especially in seasonality terms.
checkresiduals(fit.w.o.mulakat)
Breusch-Godfrey test for serial correlation of order up to 24
data: Residuals from Linear regression model
LM test = 70.519, df = 24, p-value = 1.824e-06

summary(fit.w.o.mulakat)
Call:
tslm(formula = unemployment_ts ~ t + tb1 + tb2 + seasonaldummy(unemployment_ts) +
kredi_ts + is_ilani_ts + issizlik_ts)
Residuals:
Min 1Q Median 3Q Max
-1.29919 -0.39642 -0.03167 0.31611 1.47718
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 269.180188 165.635826 1.625 0.107190
t -0.130187 0.082224 -1.583 0.116413
tb1 1.145304 0.145796 7.856 3.99e-12 ***
tb2 -2.506786 0.144222 -17.381 < 2e-16 ***
seasonaldummy(unemployment_ts)Jan 0.398427 0.268328 1.485 0.140637
seasonaldummy(unemployment_ts)Feb 0.179399 0.272355 0.659 0.511560
seasonaldummy(unemployment_ts)Mar -0.243291 0.269573 -0.903 0.368896
seasonaldummy(unemployment_ts)Apr -0.648698 0.273610 -2.371 0.019605 *
seasonaldummy(unemployment_ts)May -1.196011 0.270638 -4.419 2.46e-05 ***
seasonaldummy(unemployment_ts)Jun -1.385335 0.271883 -5.095 1.58e-06 ***
seasonaldummy(unemployment_ts)Jul -0.674922 0.272590 -2.476 0.014917 *
seasonaldummy(unemployment_ts)Aug -0.982152 0.281191 -3.493 0.000706 ***
seasonaldummy(unemployment_ts)Sep -1.153377 0.283378 -4.070 9.23e-05 ***
seasonaldummy(unemployment_ts)Oct -0.884140 0.278069 -3.180 0.001949 **
seasonaldummy(unemployment_ts)Nov -0.663254 0.273271 -2.427 0.016956 *
kredi_ts 0.014996 0.009023 1.662 0.099580 .
is_ilani_ts 0.058080 0.006534 8.889 2.17e-14 ***
issizlik_ts 0.018478 0.008574 2.155 0.033474 *
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.6008 on 103 degrees of freedom
Multiple R-squared: 0.8802, Adjusted R-squared: 0.8605
F-statistic: 44.53 on 17 and 103 DF, p-value: < 2.2e-16
residual_fitted <- data.frame(cbind(Fitted = fitted(fit.w.o.mulakat), Residuals=residuals(fit.w.o.mulakat)))
ggplot(residual_fitted, aes(x = Fitted, y = Residuals)) + geom_point() + ggtitle("Residuals vs. Fitted Values")

House Price Index
In order to get a more real House Price Index, the data is divided to
US dollar in order to get the quantities in dollars.
Seasonality can be observed especially at the time between 2014 and
2018.
There is a clear downward trend from 2014 to 2018 and an upward trend
from 2022 to 2024.
time_data_house <- c(year(min(house_index_data$Tarih)), month(min(house_index_data$Tarih)))
dollar_datapath = '/Users/ahmetkarakose/Desktop/dolar.xlsx'
dollar_data = read_excel(dollar_datapath)
New names:
dollar_data <- dollar_data[-(122:133),]
dollar_data <- dollar_data[,-3]
dollar_data$"TP DK USD A YTL" <- as.numeric(dollar_data$"TP DK USD A YTL")
names(dollar_data)[names(dollar_data) == "TP DK USD A YTL"] <- "Dollar"
dollar_data$Tarih <- paste(dollar_data$Tarih, "-01", sep = "")
dollar_data$Tarih <- as.Date(dollar_data$Tarih)
house_index_data[,2] <- house_index_data[,2] / dollar_data[,2]
house_index_ts <- ts(house_index_data$`House Price Index`, start = time_data, frequency = 12)
autoplot(house_index_ts) + ggtitle("House Price Index vs Time") + xlab("Year") + ylab("House Index 2017 = 100")

Let’s look at the autocorrelation function of the time series in
order to check seasonality. The ACF does not show any clear pattern of
seasonality in this case.
Acf(house_index_ts, lag.max = 24)

Now, we want to find predictors from Google Trends that can be
somehow related with the House Price Index in Turkey. When keywords for
this relation is thought for, these keywords are found to be logical and
related with House Price Index:
- “Satılık daire”: Obviously this keyword may be a good predictor for
House Price Index
- “Faiz”: Interest rates may increase credit rates for houses as well.
This may have a relation with House Price Index.
- “Emlak”: Obviously this keyword may be a good predictor for House
Price Index
- “İpotek”
It should be noted that maybe the lagged values of these data can be
better predictors because, people may search these terms after the House
Price Index increases. These search terms are results, so the affects of
these search terms may be delayed.
Below all of the data is gathered and time series objects are formed.
All potential predictor data are plotted and a combination of the
potential predictors are combined. These predictors are also combined
within another data frame.
satilik_daire = fread("/Users/ahmetkarakose/Desktop/satilik_daire.csv")
names(satilik_daire)[names(satilik_daire) == "satılık daire: (Türkiye)"] <- "Satılık daire"
satilik_daire_ts <- ts(satilik_daire[,-1], start = time_data, frequency = 12)
faiz = fread("/Users/ahmetkarakose/Desktop/faiz.csv")
names(faiz)[names(faiz) == "faiz: (Türkiye)"] <- "Faiz"
faiz_ts <- ts(faiz[,-1], start = time_data, frequency = 12)
emlak = fread("/Users/ahmetkarakose/Desktop/emlak.csv")
names(emlak)[names(emlak) == "emlak: (Türkiye)"] <- "Emlak"
emlak_ts <- ts(emlak[,-1], start = time_data, frequency = 12)
ipotek = fread("/Users/ahmetkarakose/Desktop/ipotek.csv")
names(ipotek)[names(ipotek) == "ipotek: (Türkiye)"] <- "İpotek"
ipotek_ts <- ts(ipotek[,-1], start = time_data, frequency = 12)
autoplot(satilik_daire_ts)

autoplot(faiz_ts)

autoplot(emlak_ts)

autoplot(ipotek_ts)

predictors_hp_index <- cbind(satilik_daire[,-1], faiz[,-1], emlak[,-1], ipotek[,-1])
df_hp_index <- cbind(house_index_data, predictors_hp_index)
Below is the correlations between each predictors and the forecast
variable. The relations of each of them can be observed below.
require(GGally)
ggpairs(df_hp_index[,-1])

Now, it’s time to create the model. Firstly the lagged data frames
for all of the selected predictors are created (Google trends data).
This is to compare the lagged models without the lagged model. Then the
piece wise linear trend is formed. Three possible models are
created:
- fit: Using all the predictors
- fit.lag1: Using all the lag-1 predictors
- fit.lag2: Using all the lag-2 predictors
The best one will be evaluated based on the lowest AIC value. As it
can be seen below, the lowest AIC value is the one with lag-1. We will
proceed with this model in the upcoming comparisons.
library(dplyr)
satilik_daire_lag <- mutate(satilik_daire,
satilik_daire_lag1 = lag(satilik_daire$`Satılık daire`, 1), # Lag 1
satilik_daire_lag2 = lag(satilik_daire$`Satılık daire`, 2), # Lag 2
)
faiz_lag <- mutate(faiz,
faiz_lag1 = lag(faiz$Faiz, 1), # Lag 1
faiz_lag2 = lag(faiz$Faiz, 2), # Lag 2
)
emlak_lag <- mutate(emlak,
emlak_lag1 = lag(emlak$Emlak, 1), # Lag 1
emlak_lag2 = lag(emlak$Emlak, 2), # Lag 2
)
ipotek_lag <- mutate(ipotek,
ipotek_lag1 = lag(ipotek$İpotek, 1), # Lag 1
ipotek_lag2 = lag(ipotek$İpotek, 2), # Lag 2
)
combined_lag <- cbind(satilik_daire_lag, faiz_lag, emlak_lag, ipotek_lag)
t <- time(unemployment_ts)
t.break1 <- 2018
t.break2 <- 2022
tb1 <- ts(pmax(0, t - t.break1), start = 2014, end = 2024, frequency = 12)
tb2 <- ts(pmax(0, t- t.break2), start = 2014, end = 2024, frequency = 12)
fit <- tslm(house_index_ts ~ satilik_daire_ts +
faiz_ts+
emlak_ts +
ipotek_ts +
t +
tb1 +
tb2)
fit.lag1 <- tslm(house_index_ts ~ t +
tb1 +
tb2 +
satilik_daire_lag1 +
faiz_lag1 +
emlak_lag1 +
ipotek_lag1, data = combined_lag)
fit.lag2 <- tslm(house_index_ts ~ t +
tb1 +
tb2 +
satilik_daire_lag2 +
faiz_lag2 +
emlak_lag2 +
ipotek_lag2, data = combined_lag)
no_lag <- CV(fit)
lag_1 <- CV(fit.lag1)
lag_2 <- CV(fit.lag2)
CV_data <- data.frame(rbind(no_lag, lag_1, lag_2))
CV_data
Now, we will inspect the model further and try to remove the
unnecessary predictor. In this case all of the predictors (Google trends
data) are removed one by one and the models are compared according to
AIC values. The lowest AIC value model is: fit.w.o.emlak. This is the
model that doesn’t contain the keyword “Emlak”. So our final model is
chosen and the residual analysis will be proceeded accordingly.
fit.everything <- tslm(house_index_ts ~ t +
tb1 +
tb2 +
satilik_daire_lag1 +
faiz_lag1 +
emlak_lag1 +
ipotek_lag1, data = combined_lag)
fit.w.o.satilik_daire <- tslm(house_index_ts ~ t +
tb1 +
tb2 +
faiz_lag1 +
emlak_lag1 +
ipotek_lag1, data = combined_lag)
fit.w.o.faiz <- tslm(house_index_ts ~ t +
tb1 +
tb2 +
satilik_daire_lag1 +
emlak_lag1 +
ipotek_lag1, data = combined_lag)
fit.w.o.emlak <- tslm(house_index_ts ~ t +
tb1 +
tb2 +
satilik_daire_lag1 +
faiz_lag1 +
ipotek_lag1, data = combined_lag)
fit.w.o.ipotek <- tslm(house_index_ts ~ t +
tb1 +
tb2 +
satilik_daire_lag1 +
faiz_lag1 +
emlak_lag1, data = combined_lag)
all <- CV(fit.everything)
no_satilik_daire <- CV(fit.w.o.satilik_daire)
no_faiz <- CV(fit.w.o.faiz)
no_emlak <- CV(fit.w.o.emlak)
no_ipotek <- CV(fit.w.o.ipotek)
CV_data <- data.frame(rbind(all, no_satilik_daire, no_faiz, no_emlak, no_ipotek))
CV_data
The model and the data are plotted in order to see visually how they
behave.
autoplot(house_index_ts, series = "Data") +
autolayer(fitted(fit.w.o.emlak), series = "Model")

From the residual analysis part we can conclude that:
- The residuals seem to have mean zero and them seem to be normally
distributed.
- However they show increasing AC especially at lags 1,2,12,18,30.
Therefore we can deduct that there is more information left out.
When considering different predictors we can observe that tb1
variable is actually not very intuitive as it has a very high
p-value.
When the Residuals vs. Fitted values graph is observed, it can be
seen that the residuals are kind of scattered around
Overall, the model seems to be adequate, however there are parts to
improve the model, especially in trend terms.
summary(fit.w.o.emlak)
Call:
tslm(formula = house_index_ts ~ t + tb1 + tb2 + satilik_daire_lag1 +
faiz_lag1 + ipotek_lag1, data = combined_lag)
Residuals:
Min 1Q Median 3Q Max
-4.7987 -1.2358 0.2498 1.1020 6.3676
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2821.06579 459.52141 6.139 1.26e-08 ***
t -1.38385 0.22807 -6.068 1.77e-08 ***
tb1 0.20114 0.39902 0.504 0.61518
tb2 17.25767 0.76319 22.613 < 2e-16 ***
satilik_daire_lag1 0.13922 0.02604 5.346 4.74e-07 ***
faiz_lag1 -0.12792 0.01565 -8.174 4.84e-13 ***
ipotek_lag1 -0.09224 0.03070 -3.005 0.00328 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.017 on 113 degrees of freedom
(1 observation deleted due to missingness)
Multiple R-squared: 0.9105, Adjusted R-squared: 0.9058
F-statistic: 191.7 on 6 and 113 DF, p-value: < 2.2e-16
checkresiduals(fit.w.o.emlak)
Breusch-Godfrey test for serial correlation of order up to 24
data: Residuals from Linear regression model
LM test = 62.284, df = 24, p-value = 3.019e-05

residual_fitted <- data.frame(cbind(Fitted = fitted(fit.w.o.emlak), Residuals=residuals(fit.w.o.emlak)))
ggplot(residual_fitted, aes(x = Fitted, y = Residuals)) + geom_point() + ggtitle("Residuals vs. Fitted Values")

Real Sector Confidence
Lastly, the regression model for the Real Sector Confidence data will
be built.
Below is the Real Sector Confidence vs. Time graph. We can make some
deductions out of it:
- There seems to be seasonality especially between 2014-2018.
- There seems to be no trend
- There is a sharp decrease in 2020 March, most probably due to the
corona-virus.
confidence_ts <- ts(confidence$"Real Sector Confidence Index", start = time_data, frequency = 12)
data.frame(confidence_ts)
autoplot(confidence_ts) + ggtitle("Real Sector Confidence vs Time") + xlab("Year") + ylab("Confidence")

Let’s look at the autocorrelation function of the time series in
order to check seasonality. The ACF does not show any clear pattern of
seasonality in this case.
ggAcf(confidence_ts, lag.max = 48)

Now, we want to find predictors from Google Trends that can be
somehow related with the Real Sector Confidence in Turkey. When keywords
for this relation is thought for, these keywords are found to be logical
and related with Real Sector Confidence
- “Faiz”: Increase in interest rates may be a bad sign for
confidence
- “Ticaret”: Increase in trade may mean more confidence
- “Uretim”: Increase in production may mean more confidence
- “İstihdam”: Increase in employment may mean more confidence
It should be noted that maybe the lagged values of these data can be
better predictors because, people may search these terms after the Real
Sector Confidence changes These search terms are results, so the affects
of these search terms may be delayed.
Below all of the data is gathered and time series objects are formed.
All potential predictor data are plotted and a combination of the
potential predictors are combined. These predictors are also combined
within another data frame.
Also a time series for corona-start dummy variable is created
ticaret = fread("/Users/ahmetkarakose/Desktop/ticaret.csv")
names(ticaret)[names(ticaret) == "ticaret: (Türkiye)"] <- "Ticaret"
ticaret_ts <- ts(ticaret[,-1], start = time_data, frequency = 12)
uretim = fread("/Users/ahmetkarakose/Desktop/uretim.csv")
names(uretim)[names(uretim) == "üretim: (Türkiye)"] <- "Üretim"
uretim_ts <- ts(uretim[,-1], start = time_data, frequency = 12)
istihdam = fread("/Users/ahmetkarakose/Desktop/istihdam.csv")
names(istihdam)[names(istihdam) == "istihdam: (Türkiye)"] <- "İstihdam"
istihdam_ts <- ts(istihdam[,-1], start = time_data, frequency = 12)
corona_values <- rep(0, 121)
corona_values[75] <- 1
corona_ts <- ts(corona_values, start = c(2014, 1), frequency = 12)
autoplot(faiz_ts)

autoplot(ticaret_ts)

autoplot(uretim_ts)

autoplot(istihdam_ts)

autoplot(corona_ts)

predictors_confidence <- cbind(faiz[,-1], ticaret[,-1], uretim[,-1], istihdam[,-1])
df_confidence <- cbind(confidence, predictors_confidence)
Below is the correlations between each predictors and the forecast
variable. The relations of each of them can be observed below.
require(GGally)
ggpairs(df_confidence[,-1])

We were not able to decide whether seasnality and trend were
necessary. Apparently the adjusted R^2 value tells us to add seasnoality
and trend as predictors
fit <- tslm(confidence_ts ~ faiz_ts +
ticaret_ts +
uretim_ts +
istihdam_ts +
corona_ts +
t +
season)
fit.season <- tslm(confidence_ts ~ faiz_ts +
ticaret_ts +
uretim_ts +
istihdam_ts +
corona_ts +
season)
fit.trend <- tslm(confidence_ts ~ faiz_ts +
ticaret_ts +
uretim_ts +
istihdam_ts +
corona_ts +
t)
fit.none <- tslm(confidence_ts ~ faiz_ts +
ticaret_ts +
uretim_ts +
istihdam_ts +
corona_ts)
no_season_no_trend <- CV(fit.trend)
season_no_trend <- CV(fit.season)
trend_no_season <- CV(fit.trend)
all <- CV(fit)
CV_data <- data.frame(rbind(no_season_no_trend, season_no_trend, trend_no_season, all))
CV_data
Nowi the lagged data frames for all of the selected predictors are
created (Google trends data). This is to compare the lagged models
without the lagged model. Then the piece wise linear trend is formed.
Three possible models are created:
- fit: Using all the predictors
- fit.lag1: Using all the lag-1 predictors
- fit.lag2: Using all the lag-2 predictors
The best one will be evaluated based on the lowest AIC value. As it
can be seen below, the lowest AIC value is the one with no lag. We will
proceed with this model in the upcoming comparisons.
library(dplyr)
faiz_lag <- mutate(faiz,
faiz_lag1 = lag(faiz$Faiz, 1), # Lag 1
faiz_lag2 = lag(faiz$Faiz, 2), # Lag 2
)
ticaret_lag <- mutate(ticaret,
ticaret_lag1 = lag(ticaret$Ticaret, 1), # Lag 1
ticaret_lag2 = lag(ticaret$Ticaret, 2), # Lag 2
)
uretim_lag <- mutate(uretim,
uretim_lag1 = lag(uretim$Üretim, 1), # Lag 1
uretim_lag2 = lag(uretim$Üretim, 2), # Lag 2
)
istihdam_lag <- mutate(istihdam,
istihdam_lag1 = lag(istihdam$İstihdam, 1), # Lag 1
istihdam_lag2 = lag(istihdam$İstihdam, 2), # Lag 2
)
combined_lag <- cbind(faiz_lag, ticaret_lag, uretim_lag, istihdam_lag)
fit <- tslm(confidence_ts ~ faiz_ts +
ticaret_ts +
uretim_ts +
istihdam_ts +
corona_ts +
t +
season)
fit.lag1 <- tslm(confidence_ts ~ t +
season +
faiz_lag1 +
ticaret_lag1 +
uretim_lag1 +
istihdam_lag1, data = combined_lag)
fit.lag2 <- tslm(confidence_ts ~ t +
season +
faiz_lag2 +
ticaret_lag2 +
uretim_lag2 +
istihdam_lag2, data = combined_lag)
no_lag <- CV(fit)
lag_1 <- CV(fit.lag1)
lag_2 <- CV(fit.lag2)
CV_data <- data.frame(rbind(no_lag, lag_1, lag_2))
CV_data
Now, we will inspect the model further and try to remove the
unnecessary predictor. In this case all of the predictors (Google trends
data) are removed one by one and the models are compared according to
AIC and adj. R^2 values. The best models are fit.everything and
fit.w.o.corona respectively for adj. R^2 value and AIC value. We will
proceed with fit.everything
fit.everything <- tslm(confidence_ts ~ faiz_ts +
ticaret_ts +
uretim_ts +
istihdam_ts +
corona_ts +
t +
season)
fit.w.o.faiz <- tslm(confidence_ts ~ ticaret_ts +
uretim_ts +
istihdam_ts +
corona_ts +
t +
season)
fit.w.o.ticaret <- tslm(confidence_ts ~ faiz_ts +
uretim_ts +
istihdam_ts +
corona_ts +
t +
season)
fit.w.o.uretim <- tslm(confidence_ts ~ faiz_ts +
ticaret_ts +
istihdam_ts +
corona_ts +
t +
season)
fit.w.o.istihdam <- tslm(confidence_ts ~ faiz_ts +
ticaret_ts +
uretim_ts +
corona_ts +
t +
season)
fit.w.o.corona <- tslm(confidence_ts ~ faiz_ts +
ticaret_ts +
uretim_ts +
istihdam_ts +
t +
season)
all <- CV(fit.everything)
no_faiz <- CV(fit.w.o.faiz)
no_ticaret <- CV(fit.w.o.ticaret)
no_uretim <- CV(fit.w.o.uretim)
no_istihdam <- CV(fit.w.o.istihdam)
no_corona <- CV(fit.w.o.corona)
CV_data <- data.frame(rbind(all, no_faiz, no_ticaret, no_uretim, no_istihdam, no_corona))
CV_data
The model and the data are plotted in order to see visually how they
behave.
autoplot(confidence_ts, series = "Data") +
autolayer(fitted(fit.everything), series = "Model")

From the residual analysis part we can conclude that:
- The residuals seem to have mean zero and them seem to be normally
distributed.
- However the data show very high autocorrelation between
residuals.
When considering different predictors we can observe that most of the
seasonality values are not that informative (We were not sure whether to
add to the model)
When the Residuals vs. Fitted values graph is observed, it can be
seen that the residuals are kind of scattered around
Overall, the model seems to deosn’t seem adequate as there is really
high AC between residuals and the adjusted R^2 value is pretty
small.
summary(fit.everything)
Call:
tslm(formula = confidence_ts ~ faiz_ts + ticaret_ts + uretim_ts +
istihdam_ts + corona_ts + t + season)
Residuals:
Min 1Q Median 3Q Max
-13.653 -3.027 0.078 2.875 12.643
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -3.961e+03 7.178e+02 -5.518 2.57e-07 ***
faiz_ts -2.094e-01 4.156e-02 -5.039 2.01e-06 ***
ticaret_ts 2.791e-01 7.225e-02 3.863 0.000196 ***
uretim_ts 7.685e-02 6.997e-02 1.098 0.274595
istihdam_ts -4.171e-01 5.774e-02 -7.224 9.04e-11 ***
corona_ts -6.794e+00 5.611e+00 -1.211 0.228731
t 2.010e+00 3.570e-01 5.629 1.57e-07 ***
season2 1.865e+00 2.279e+00 0.818 0.415120
season3 6.576e+00 2.391e+00 2.750 0.007035 **
season4 5.427e+00 2.348e+00 2.311 0.022808 *
season5 5.882e+00 2.313e+00 2.543 0.012467 *
season6 5.242e+00 2.306e+00 2.273 0.025111 *
season7 2.794e+00 2.478e+00 1.128 0.262144
season8 -4.489e-01 2.502e+00 -0.179 0.857996
season9 -1.472e-01 2.565e+00 -0.057 0.954331
season10 -2.640e-02 2.329e+00 -0.011 0.990978
season11 -7.249e-01 2.301e+00 -0.315 0.753368
season12 -1.029e+00 2.277e+00 -0.452 0.652113
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 5.192 on 103 degrees of freedom
Multiple R-squared: 0.5139, Adjusted R-squared: 0.4337
F-statistic: 6.406 on 17 and 103 DF, p-value: 5.08e-10
checkresiduals(fit.everything)
Breusch-Godfrey test for serial correlation of order up to 24
data: Residuals from Linear regression model
LM test = 65.874, df = 24, p-value = 9.054e-06

residual_fitted <- data.frame(cbind(Fitted = fitted(fit.everything), Residuals=residuals(fit.everything)))
ggplot(residual_fitted, aes(x = Fitted, y = Residuals)) + geom_point() + ggtitle("Residuals vs. Fitted Values")

Conclusion
Overall, we have built three regression models in three different
time series. Even though some of the models were better than the other
models there was one common problem: autocorrelation between residuals.
In all of the models the ACF graph was not as desired and this remarked
further investigation on the model.
However other than this, this assignment tought how to build models,
select predictors, compare models and do residual analysis for different
time series and was benefitary.
Appendices
ChatGPT:
- Help from LLM in order to create dataframes add and subtract columns
and rows and also for creating lagged data.
LS0tCnRpdGxlOiAiSFcxIFRpbWUgU2VyaWVzIFJlZ3Jlc3Npb24iCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMjIEludHJvZHVjdGlvbgoKSW4gdGhpcyBwcm9qZWN0LCByZWdyZXNzaW9uIG1vZGVscyBmb3IgdGhyZWUgZGlmZmVyZW50IHRpbWVzIHNlcmllcyBkYXRhIHdpbGwgYmUgYnVpbHQuIFRoZXNlIGRhdGEgYXJlIGNvbGxlY3RlZCBmcm9tIENlbnRyYWwgQmFuayBvZiB0aGUgUmVwdWJsaWMgb2YgVHVya2V5LiB0aGUgY2hvc2VuIGRhdGEgYXJlOgoKLSAgIFVuZW1wbG95bWVudCBwZXJjZW50YWdlCi0gICBIb3VzZSBwcmljZSBpbmRleAotICAgUmVhbCBzZWN0b3IgY29uZmlkZW5jZSBpbmRleAoKQWxsIG9mIHRoZXNlIGRhdGEgYXJlIG1vbnRobHkgYW5kIHdlIGhhdmUgdGhlIHRpbWUgc2VyaWVzIGZvciB0aGVtIGZyb20gMDEtMjAxNCB0byAwMS0yMDI0LiBUaGVyZWZvcmUgdGhleSBjYW4gYmUgcGxvdHRlZCBhZ2FpbnN0IHRoZW1zZWx2ZXMuCgpUaGUgYmFzaWMgYXBwcm9hY2ggdG8gdGhlIHByb2JsZW0gaXMgbGlrZSB0aGlzOiBXZSBhc2sgb3Vyc2VsdmVzIHdoYXQgY291bGQgdGhlc2UgZm9yZWNhc3QgdmFyaWFibGVzIGJlIHJlbGF0ZWQgdG8/CgpBZnRlciBmaW5kaW5nIHRoZSBwb3RlbnRpYWwgYW5zd2VycywgdGhlc2UgYW5zd2VycyBhcmUgc2VhcmNoZWQgaW4gR29vZ2xlIHRyZW5kcyBkYXRhIGFuZCBkb3dubG9hZGVkLiBBbHNvIHRoZSB0aW1lIHNlcmllcyBwbG90IGlzIG9ic2VydmVkIGluIG9yZGVyIHRvIHNlZSBhbnkgdHJlbmQgb3Igc2Vhc29uYWxpdHkgYW5kIGFkZCB0aGVtIGFzIHByZWRpY3RvcnMgYXMgd2VsbC4KCkFmdGVyIHRoZSBwcmVkaWN0b3JzIGFyZSBkZWNpZGVkIG9uIHNldmVyYWwgbW9kZWxzIGFyZSBidWlsdCBieSB1c2luZyBhbGwgb2YgdGhlbSBhbmQgcmVtb3Zpbmcgc29tZSBvZiB0aGVtLiB0aGVuIHRoZXNlIG1vZGVscyBhcmUgY29tcGFyZWQgdXNpbmcgdGVzdHMgc3VjaCBhcyBBSUMgb3IgYWRqdXN0ZWQgUiBzcXVhcmVkLgoKQWZ0ZXIgZGVjaWRpbmcgb24gd2hpY2ggcHJlZGljdG9ycyB0byB1c2UsIHdlIGNhbiBwcm9jZWVkIHdpdGggb3VyIGZpbmFsIGRlY2lkZWQgbW9kZWwuIFRoZSBmaW5hbCBkZWNpZGVkIG1vZGVsIGlzIHBsb3R0ZWQgYWdhaW5zIHRoZSByZWFsIGRhdGEgaW4gb3JkZXIgdG8gc2VlIGhvdyBnb29kIHRoZSBtb2RlbCBpcy4KCkZpbmFsbHksIHRoZSByZXNpZHVhbHMgYXJlIGV2YWx1YXRlZC4gSW4gdGhpcyBwYXJ0LCB3ZSB0cnkgdG8gYW5zd2VyIHdoZXRoZXIgb3VyIGFzc3VtcHRpb25zIGFib3V0IHRoZSByZXNpZHVhbHMgYXJlIGNvcnJlY3QuIFRoZXNlIGFyZToKCi0gICBUaGV5IGhhdmUgbWVhbiB6ZXJvCi0gICBEaXN0cmlidXRlZCBhcHByb3hpbWF0ZWx5IG5vcm1hbAotICAgVGhleSBkb24ndCBoYXZlIGF1dG9jb3JyZWxhdGlvbgoKSWYgYWxsIHRocmVlIG9mIHRoZXNlIGFwcGx5IHRoZW4gd2UgY2FuIGNvbmNsdWRlIHRoYXQgd2UgaGF2ZSBhIGRlY2VudCBtb2RlbC4KCkZpcnN0bHkgcmVxdWlyZSB0aGUgbmVjZXNzYXJ5IGxpYnJhcmllcyBhbmQgc2V0IHRoZSBwbG90IHdpbmRvdywgaGVpZ2h0IGFuZCB3aWR0aC4KCmBgYHtyfQpyZXF1aXJlKGRhdGEudGFibGUpCnJlcXVpcmUobHVicmlkYXRlKQpyZXF1aXJlKGZvcmVjYXN0KQpyZXF1aXJlKHNraW1yKQpyZXF1aXJlKHJlcHIpCnJlcXVpcmUocmVhZHhsKQpyZXF1aXJlKGdncGxvdDIpCgoKb3B0aW9ucyhyZXByLnBsb3Qud2lkdGg9MTIuNywgcmVwci5wbG90LmhlaWdodD04LjUpCmBgYAoKQ3JlYXRlIGRhdGEgdGFibGVzIGZvciBvdXIgdGhyZWUgZm9yZWNhc3QgdmFyaWFibGVzLgoKYGBge3J9CmRhdGFfcGF0aF91bmVtcGxveW1lbnQgPScvVXNlcnMvYWhtZXRrYXJha29zZS9EZXNrdG9wL0VWRFMueGxzeCcKdW5lbXBsb3ltZW50X2RhdGEgPSByZWFkX2V4Y2VsKGRhdGFfcGF0aCkKCmRhdGFfcGF0aF9ob3VzaW5nID0gJy9Vc2Vycy9haG1ldGthcmFrb3NlL0Rlc2t0b3Ava29udXRfZml5YXQueGxzeCcKaG91c2VfaW5kZXhfZGF0YSA9IHJlYWRfZXhjZWwoZGF0YV9wYXRoX2hvdXNpbmcpCgpkYXRhX3BhdGhfY29uZmlkZW5jZSA9ICcvVXNlcnMvYWhtZXRrYXJha29zZS9EZXNrdG9wL2NvbmZpZGVuY2UueGxzeCcKY29uZmlkZW5jZSA9IHJlYWRfZXhjZWwoZGF0YV9wYXRoX2NvbmZpZGVuY2UpCgpgYGAKCk1hbmlwdWxhdGUgYW5kIGNsZWFuIHRoZSBkYXRhLCBzbyBpdCdzIGF0IGEgZGVzaXJlZCBmb3JtYXQuIE1ha2UgdGhlIGZvcmVjYXN0IHZhbHVlcyBhcyB0eXBlIG51bWVyaWMuIFJlbmFtZSB0aGUgZm9yZWNhc3QgdmFyaWFibGUgY29sdW1uIHRvIGEgbW9yZSByZWFkYWJsZSB0aXRsZSBhbmQgbWFrZSB0aGUgZGF0ZSBjb2x1bW4gYXMgZGF0ZSB0eXBlLgoKQWxzbywgY3JlYXRlIGEgY29tYmluZWQgdmVyc2lvbiBvZiB0aGVzZSB0aHJlZSBkYXRhLgoKYGBge3J9CnVuZW1wbG95bWVudF9kYXRhIDwtIHVuZW1wbG95bWVudF9kYXRhWy0oMTIyOjEzMyksXQp1bmVtcGxveW1lbnRfZGF0YSA8LSB1bmVtcGxveW1lbnRfZGF0YVssLTNdCnVuZW1wbG95bWVudF9kYXRhJCJUUCBZSVNHVUNVMiBHOCIgIDwtIGFzLm51bWVyaWModW5lbXBsb3ltZW50X2RhdGEkIlRQIFlJU0dVQ1UyIEc4IikKbmFtZXModW5lbXBsb3ltZW50X2RhdGEpW25hbWVzKHVuZW1wbG95bWVudF9kYXRhKSA9PSAiVFAgWUlTR1VDVTIgRzgiXSA8LSAiVW5lbXBsb3ltZW50Igp1bmVtcGxveW1lbnRfZGF0YSREYXRlIDwtIHBhc3RlKHVuZW1wbG95bWVudF9kYXRhJERhdGUsICItMDEiLCBzZXAgPSAiIikKdW5lbXBsb3ltZW50X2RhdGEkRGF0ZSA8LSBhcy5EYXRlKHVuZW1wbG95bWVudF9kYXRhJERhdGUpCgpob3VzZV9pbmRleF9kYXRhIDwtIGhvdXNlX2luZGV4X2RhdGFbLSgxMjI6MTMzKSxdCmhvdXNlX2luZGV4X2RhdGEgPC0gaG91c2VfaW5kZXhfZGF0YVssLTNdCmhvdXNlX2luZGV4X2RhdGEkIlRQIEhLRkUwMSIgIDwtIGFzLm51bWVyaWMoaG91c2VfaW5kZXhfZGF0YSQiVFAgSEtGRTAxIikKbmFtZXMoaG91c2VfaW5kZXhfZGF0YSlbbmFtZXMoaG91c2VfaW5kZXhfZGF0YSkgPT0gIlRQIEhLRkUwMSJdIDwtICJIb3VzZSBQcmljZSBJbmRleCIKaG91c2VfaW5kZXhfZGF0YSRUYXJpaCA8LSBwYXN0ZShob3VzZV9pbmRleF9kYXRhJFRhcmloLCAiLTAxIiwgc2VwID0gIiIpCmhvdXNlX2luZGV4X2RhdGEkVGFyaWggPC0gYXMuRGF0ZShob3VzZV9pbmRleF9kYXRhJFRhcmloKQoKY29uZmlkZW5jZSA8LSBjb25maWRlbmNlWy0oMTIyOjEzMyksXQpjb25maWRlbmNlIDwtIGNvbmZpZGVuY2VbLC0zXQpjb25maWRlbmNlJCJUUCBHWTEgTjIiICA8LSBhcy5udW1lcmljKGNvbmZpZGVuY2UkIlRQIEdZMSBOMiIpCm5hbWVzKGNvbmZpZGVuY2UpW25hbWVzKGNvbmZpZGVuY2UpID09ICJUUCBHWTEgTjIiXSA8LSAiUmVhbCBTZWN0b3IgQ29uZmlkZW5jZSBJbmRleCIKY29uZmlkZW5jZSREYXRlIDwtIHBhc3RlKGNvbmZpZGVuY2UkRGF0ZSwgIi0wMSIsIHNlcCA9ICIiKQpjb25maWRlbmNlJERhdGUgPC0gYXMuRGF0ZShjb25maWRlbmNlJERhdGUpCgpjb21iaW5lZCA8LSBjYmluZCh1bmVtcGxveW1lbnRfZGF0YVssMl0sIGhvdXNlX2luZGV4X2RhdGFbLDJdLCBjb25maWRlbmNlWywyXSkKY29tYmluZWQKYGBgCgpJbiBvcmRlciB0byBzZWUgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gZGF0YSwgcGxvdCBlYWNoIGZvcmVjYXN0IHZhcmlhYmxlIGFnYWlucyB0aGUgb3RoZXIgb25lIGFuZCBzZWUgdGhlaXIgY29ycmVsYXRpb24gdmFsdWVzLiBUaGV5IG5lZWQgdG8gYmUgbGVzcyB0aGFuIDAuNSBpbiBvcmRlciB0byBwcm9jZWVkIHdpdGggdGhlc2UgZm9yZWNhc3QgdmFyYWlibGVzLgoKQXMgaXQgY2FuIGJlIHNlZW4gYmVsb3cgdGhlIGNvcnJlbGF0aW9ucyBhcmU6CgotICAgLTAuMzk4IGZvciBIb3VzZSBQcmljZSBJbmRleCB2cy4gVW5lbXBsb3ltZW50Ci0gICAtMC4zMTAgZm9yIFJlYWwgU2VjdG9yIENvbmZpZGVuY2UgdnMuIFVuZW1wbG95bWVudAotICAgLTAuMDEwIGZvciBSZWFsIFNlY3RvciBDb25maWRlbmNlIHZzLiBIb3VzZSBQcmljZSBJbmRleAoKYGBge3J9CnJlcXVpcmUoR0dhbGx5KQpnZ3BhaXJzKGNvbWJpbmVkKQpgYGAKCiMjIFVuZW1wbG95bWVudAoKRmlyc3RseSwgdGhlIHJlZ3Jlc3Npb24gbW9kZWwgZm9yIHRoZSBVbmVtcGxveW1lbnQgZGF0YSB3aWxsIGJlIGJ1aWx0LgoKQmVsb3cgaXMgdGhlIFVuZW1wbG95bWVudCB2cy4gVGltZSBncmFwaC4gV2UgY2FuIG1ha2Ugc29tZSBkZWR1Y3Rpb25zIG91dCBvZiBpdDoKCi0gICBUaGVyZSBpcyBhbiBvYnZpb3VzIHNlYXNvbmFsaXR5IGJldHdlZW4gMjAxNCAtIDIwMTggYW5kIDIwMjEtMjAyNC4gU28gc2Vhc29uYWxpdHkgY2FuIGJlIGFkZGVkIHRvIG91ciBtb2RlbC4KLSAgIEFsc28gdGhlcmUgaXMgaW5jcmVhc2luZyB0cmVuZCBiZXR3ZWVuIDIwMTQtMjAxOCBhbmQgZGVjcmVhc2luZyB0cmVuZCBiZXR3ZWVuIDIwMjEtMjAyNC4gQSBwaWVjZXdpc2UgdHJlbmQgY291bGQgYmUgYWRkZWQgdG8gb3VyIG1vZGVsLgotICAgVGhlcmUgaXMgYSBzaGFycCBpbmNyZWFzZSBpbiAyMDE5LgoKYGBge3J9CnRpbWVfZGF0YSA8LSBjKHllYXIobWluKHVuZW1wbG95bWVudF9kYXRhJERhdGUpKSwgbW9udGgobWluKHVuZW1wbG95bWVudF9kYXRhJERhdGUpKSkKdW5lbXBsb3ltZW50X3RzIDwtIHRzKHVuZW1wbG95bWVudF9kYXRhJFVuZW1wbG95bWVudCwgc3RhcnQgPSB0aW1lX2RhdGEsIGZyZXF1ZW5jeSA9IDEyKQoKYXV0b3Bsb3QodW5lbXBsb3ltZW50X3RzKSArIGdndGl0bGUoIlVuZW1wbG95bWVudCAoJSkgdnMgVGltZSIpICsgeGxhYigiWWVhciIpICsgeWxhYigiVW5lbXBsb3ltZW50ICglKSIpCmBgYAoKV2hlbiB3ZSBvYnNlcnZlIHRoZSBBQ0YgZnVuY3Rpb24gZm9yIHRoZSB0aW1lIHNlcmllcyB3ZSBjYW4gb2JzZXJ2ZSBhbiBpbmNyZWFzZSBpbiBsYWctMTIgYW5kIGxhZy0yNC4gVGhpcyBwcm92ZXMgdGhlcmUgaXMgc2Vhc29uYWxpdHkgaW4gZGF0YS4KCmBgYHtyfQpnZ0FjZih1bmVtcGxveW1lbnRfdHMsIGxhZy5tYXggPSA0OCkgKyBnZ3RpdGxlKCJVbmVtcGxveW1lbnQgQUNGIikKYGBgCgpOb3csIHdlIHdhbnQgdG8gZmluZCBwcmVkaWN0b3JzIGZyb20gR29vZ2xlIFRyZW5kcyB0aGF0IGNhbiBiZSBzb21laG93IHJlbGF0ZWQgd2l0aCB0aGUgVW5lbXBsb3ltZW50IGluIFR1cmtleS4gV2hlbiBrZXl3b3JkcyBmb3IgdGhpcyByZWxhdGlvbiBpcyB0aG91Z2h0IGZvciwgdGhlc2Uga2V5d29yZHMgYXJlIGZvdW5kIHRvIGJlIGxvZ2ljYWwgYW5kIHJlbGF0ZWQgd2l0aCBVbmVtcGxveW1lbnQ6CgotICAgIktyZWRpIjogTWF5YmUgcGVvcGxlIGFyZSBzZWVraW5nIGZvciBtb3JlIGNyZWRpdHMgd2hlbiB1bmVtcGxveW1lbnQgaW5jcmVhc2VzCi0gICAixLDFnyBpbGFuxLEiOiBQZW9wbGUgbWF5IGJlIHNlZWtpbmcgbW9yZSBqb2JzIHdoZW4gdW5lbXBsb3ltZW50IGluY3JlYXNlcy4KLSAgICLEsMWfc2l6bGlrIjogT2J2aW91c2x5IHBlb3BsZSB3aWxsIHNlYXJjaCB0aGlzIHRlcm0gd2hlbiB1bmVtcGxveW1lbnQgaW5jcmVhc2VzCi0gICAiTcO8bGFrYXQiOiBNYXliZSBwZW9wbGUgYXJlIHNlZWtpbmcgZm9yIG1vcmUgaW50ZXJ2aWV3cyBiZWNhdXNlIHRoZXkgd2FudCB0byBlbnRlciBuZXcgam9icy4KCkl0IHNob3VsZCBiZSBub3RlZCB0aGF0IG1heWJlIHRoZSBsYWdnZWQgdmFsdWVzIG9mIHRoZXNlIGRhdGEgY2FuIGJlIGJldHRlciBwcmVkaWN0b3JzIGJlY2F1c2UsIHBlb3BsZSB3b3VsZCBzZWFyY2ggdGhlc2UgdGVybXMgYWZ0ZXIgVW5lbXBsb3ltZW50IGluY3JlYXNlcy4gVGhlc2Ugc2VhcmNoIHRlcm1zIGFyZSByZXN1bHRzLCBzbyB0aGUgYWZmZWN0cyBvZiB0aGVzZSBzZWFyY2ggdGVybXMgbWF5IGJlIGRlbGF5ZWQuCgpCZWxvdyBhbGwgb2YgdGhlIGRhdGEgaXMgZ2F0aGVyZWQgYW5kIHRpbWUgc2VyaWVzIG9iamVjdHMgYXJlIGZvcm1lZC4gQWxsIHBvdGVudGlhbCBwcmVkaWN0b3IgZGF0YSBhcmUgcGxvdHRlZCBhbmQgYSBjb21iaW5hdGlvbiBvZiB0aGUgcG90ZW50aWwgcHJlZGljdG9ycyBhcmUgY29tYmluZWQuIFRoZXNlIHByZWRpY3RvcnMgYXJlIGFsc28gY29tYmluZWQgd2l0aGluIGFub3RoZXIgZGF0YWZyYW1lLgoKYGBge3J9CmtyZWRpID0gZnJlYWQoIi9Vc2Vycy9haG1ldGthcmFrb3NlL0Rlc2t0b3Ava3JlZGkuY3N2IikKbmFtZXMoa3JlZGkpW25hbWVzKGtyZWRpKSA9PSAia3JlZGk6IChUw7xya2l5ZSkiXSA8LSAiS3JlZGkiCmtyZWRpX3RzIDwtIHRzKGNyZWRpdF9kYXRhWywtMV0sIHN0YXJ0ID0gdGltZV9kYXRhLCBmcmVxdWVuY3kgPSAxMikKCmlzX2lsYW5pID0gZnJlYWQoIi9Vc2Vycy9haG1ldGthcmFrb3NlL0Rlc2t0b3AvaXNfaWxhbmkuY3N2IikKbmFtZXMoaXNfaWxhbmkpW25hbWVzKGlzX2lsYW5pKSA9PSAiacWfIGlsYW7EsTogKFTDvHJraXllKSJdIDwtICLEsMWfIGlsYW7EsSIKaXNfaWxhbmlfdHMgPC0gdHMoaXNfaWxhbmlbLC0xXSwgc3RhcnQgPSB0aW1lX2RhdGEsIGZyZXF1ZW5jeSA9IDEyKQoKaXNzaXpsaWsgPSBmcmVhZCgiL1VzZXJzL2FobWV0a2FyYWtvc2UvRGVza3RvcC9pc3Npemxpay5jc3YiKQpuYW1lcyhpc3NpemxpaylbbmFtZXMoaXNzaXpsaWspID09ICJpxZ9zaXpsaWs6IChUw7xya2l5ZSkiXSA8LSAixLDFn3NpemxpayIKaXNzaXpsaWtfdHMgPC0gdHMoaXNzaXpsaWtbLC0xXSwgc3RhcnQgPSB0aW1lX2RhdGEsIGZyZXF1ZW5jeSA9IDEyKQoKbXVsYWthdCA9IGZyZWFkKCIvVXNlcnMvYWhtZXRrYXJha29zZS9EZXNrdG9wL211bGFrYXQuY3N2IikKbmFtZXMobXVsYWthdClbbmFtZXMobXVsYWthdCkgPT0gIm3DvGxha2F0OiAoVMO8cmtpeWUpIl0gPC0gIk3DvGxha2F0IgptdWxha2F0X3RzIDwtIHRzKGludGVydmlld19kYXRhWywtMV0sIHN0YXJ0ID0gdGltZV9kYXRhLCBmcmVxdWVuY3kgPSAxMikKCmF1dG9wbG90KGtyZWRpX3RzKQphdXRvcGxvdChpc19pbGFuaV90cykKYXV0b3Bsb3QoaXNzaXpsaWtfdHMpCmF1dG9wbG90KG11bGFrYXRfdHMpCgpwcmVkaWN0b3JzX3VuZW1wbG95bWVudCA8LSBjYmluZChrcmVkaVssLTFdLCBpc19pbGFuaVssLTFdLCBpc3Npemxpa1ssLTFdLCBtdWxha2F0WywtMV0pCmRmX3VuZW1wbG95bWVudCA8LSBjYmluZCh1bmVtcGxveW1lbnRfZGF0YSwgcHJlZGljdG9ycykKYGBgCgpCZWxvdyBpcyB0aGUgY29ycmVsYXRpb25zIGJldHdlZW4gZWFjaCBwcmVkaWN0b3JzIGFuZCB0aGUgZm9yZWNhc3QgdmFyaWFibGUuIFRoZSByZWxhdGlvbnMgb2YgZWFjaCBvZiB0aGVtIGNhbiBiZSBvYnNlcnZlZCBiZWxvdy4KCmBgYHtyfQpyZXF1aXJlKEdHYWxseSkKZ2dwYWlycyhkZlssLTFdKQpgYGAKCk5vdywgaXQncyB0aW1lIHRvIGNyZWF0ZSB0aGUgbW9kZWwuIEZpcnN0bHkgdGhlIGxhZ2dlZCBkYXRhZnJhbWVzIGZvciBhbGwgb2YgdGhlIHNlbGVjdGVkIHByZWRpY3RvcnMgYXJlIGNyZWF0ZWQgKGdvb2dsZSB0cmVuZHMgZGF0YSkuIFRoaXMgaXMgdG8gY29tcGFyZSB0aGUgbGFnZ2VkIG1vZGVscyB3aXRob3V0IHRoZSBsYWdnZWQgbW9kZWwuIFRoZW4gdGhlIHBpZWNld2lzZSBsaW5lYXIgdHJlbmQgaXMgZm9ybWVkLiBJbiB0aGUgbW9kZWwgc2Vhc29uYWwgZHVtbXkgdmFyaWFibGVzIGFyZSBhbHNvIGFkZGVkLiBUaHJlZSBwb3NzaWJsZSBtb2RlbHMgYXJlIGNyZWF0ZWQ6CgotICAgZml0OiBVc2luZyBhbGwgdGhlIHByZWRpY3RvcnMKLSAgIGZpdC5sYWcxOiBVc2luZyBhbGwgdGhlIGxhZy0xIHByZWRpY3RvcnMKLSAgIGZpdC5sYWcyOiBVc2luZyBhbGwgdGhlIGxhZy0yIHByZWRpY3RvcnMKClRoZSBiZXN0IG9uZSB3aWxsIGJlIGV2YWx1YXRlZCBiYXNlZCBvbiB0aGUgbG93ZXN0IEFJQyB2YWx1ZS4gQXMgaXQgY2FuIGJlIHNlZW4gYmVsb3csIHRoZSBsb3dlc3QgQUlDIHZhbHVlIGlzIHRoZSBvbmUgd2l0aCBub19sYWcuIFdlIHdpbGwgcHJvY2VlZCB3aXRoIHRoaXMgbW9kZWwgaW4gdGhlIHVwY29taW5nIGNvbXBhcmlzb25zLgoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmtyZWRpX2xhZyA8LSBtdXRhdGUoa3JlZGksCiAgICAgICAgICAgICAgIGtyZWRpX2xhZzEgPSBsYWcoa3JlZGkkS3JlZGksIDEpLCAgIyBMYWcgMQogICAgICAgICAgICAgICBrcmVkaV9sYWcyID0gbGFnKGtyZWRpJEtyZWRpLCAyKSwgICMgTGFnIDIKICAgICAgICAgICAgICAgKQoKaXNfaWxhbmlfbGFnIDwtIG11dGF0ZShpc19pbGFuaSwKICAgICAgICAgICAgICAgaXNfaWxhbmlfbGFnMSA9IGxhZyhpc19pbGFuaSQixLDFnyBpbGFuxLEiLCAxKSwgICMgTGFnIDEKICAgICAgICAgICAgICAgaXNfaWxhbmlfbGFnMiA9IGxhZyhpc19pbGFuaSQixLDFnyBpbGFuxLEiLCAyKSwgICMgTGFnIDIKICAgICAgICAgICAgICAgKQoKaXNzaXpsaWtfbGFnIDwtIG11dGF0ZShpc3NpemxpaywKICAgICAgICAgICAgICAgaXNzaXpsaWtfbGFnMSA9IGxhZyhpc3NpemxpayQixLDFn3NpemxpayIsIDEpLCAgIyBMYWcgMQogICAgICAgICAgICAgICBpc3Npemxpa19sYWcyID0gbGFnKGlzc2l6bGlrJCLEsMWfc2l6bGlrIiwgMiksICAjIExhZyAyCiAgICAgICAgICAgICAgICkKCm11bGFrYXRfbGFnIDwtIG11dGF0ZShtdWxha2F0LAogICAgICAgICAgICAgICBtdWxha2F0X2xhZzEgPSBsYWcobXVsYWthdCQiTcO8bGFrYXQiLCAxKSwgICMgTGFnIDEKICAgICAgICAgICAgICAgbXVsYWthdF9sYWcyID0gbGFnKG11bGFrYXQkIk3DvGxha2F0IiwgMiksICAjIExhZyAyCiAgICAgICAgICAgICAgICkKCmNvbWJpbmVkX2xhZyA8LSBjYmluZChrcmVkaV9sYWcsIGlzX2lsYW5pX2xhZywgaXNzaXpsaWtfbGFnLCBtdWxha2F0X2xhZykKCnQgPC0gdGltZSh1bmVtcGxveW1lbnRfdHMpCnQuYnJlYWsxIDwtIDIwMTgKdC5icmVhazIgPC0gMjAyMQp0YjEgPC0gdHMocG1heCgwLCB0IC0gdC5icmVhazEpLCBzdGFydCA9IDIwMTQsIGVuZCA9IDIwMjQsIGZyZXF1ZW5jeSA9IDEyKQp0YjIgPC0gdHMocG1heCgwLCB0LSB0LmJyZWFrMiksIHN0YXJ0ID0gMjAxNCwgZW5kID0gMjAyNCwgZnJlcXVlbmN5ID0gMTIpCgpmaXQgPC0gdHNsbSh1bmVtcGxveW1lbnRfdHMgfiB0ICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRiMSArIAogICAgICAgICAgICAgICAgICAgICAgICB0YjIgKyAKICAgICAgICAgICAgICAgICAgICAgICAgc2Vhc29uYWxkdW1teSh1bmVtcGxveW1lbnRfdHMpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGtyZWRpX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGlzX2lsYW5pX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGlzc2l6bGlrX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIG11bGFrYXRfdHMpCgpmaXQubGFnMSA8LSB0c2xtKHVuZW1wbG95bWVudF90cyB+IHQgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGIxICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRiMiArIAogICAgICAgICAgICAgICAgICAgICAgICBzZWFzb25hbGR1bW15KHVuZW1wbG95bWVudF90cykgKyAKICAgICAgICAgICAgICAgICAgICAgICAga3JlZGlfbGFnMSArIAogICAgICAgICAgICAgICAgICAgICAgICBpc19pbGFuaV9sYWcxICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGlzc2l6bGlrX2xhZzEgKyAKICAgICAgICAgICAgICAgICAgICAgICAgbXVsYWthdF9sYWcxLCBkYXRhID0gY29tYmluZWRfbGFnKQoKZml0LmxhZzIgPC0gdHNsbSh1bmVtcGxveW1lbnRfdHMgfiB0ICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRiMSArIAogICAgICAgICAgICAgICAgICAgICAgICB0YjIgKyAKICAgICAgICAgICAgICAgICAgICAgICAgc2Vhc29uYWxkdW1teSh1bmVtcGxveW1lbnRfdHMpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGtyZWRpX2xhZzIgKyAKICAgICAgICAgICAgICAgICAgICAgICAgaXNfaWxhbmlfbGFnMiArIAogICAgICAgICAgICAgICAgICAgICAgICBpc3Npemxpa19sYWcyICsgCiAgICAgICAgICAgICAgICAgICAgICAgIG11bGFrYXRfbGFnMiwgZGF0YSA9IGNvbWJpbmVkX2xhZykKCm5vX2xhZyA8LSBDVihmaXQpCmxhZ18xIDwtIENWKGZpdC5sYWcxKQpsYWdfMiA8LSBDVihmaXQubGFnMikKQ1ZfZGF0YSA8LSBkYXRhLmZyYW1lKHJiaW5kKG5vX2xhZywgbGFnXzEsIGxhZ18yKSkKQ1ZfZGF0YQpgYGAKCk5vdywgd2Ugd2lsbCBpbnNwZWN0IHRoZSBtb2RlbCBmdXJ0aGVyIGFuZCB0cnkgdG8gcmVtb3ZlIHRoZSB1bm5lY2Vzc2FyeSBwcmVkaWN0b3IuIEluIHRoaXMgY2FzZSBhbGwgb2YgdGhlIHByZWRpY3RvcnMgKGdvb2dsZSB0cmVuZHMgZGF0YSkgYXJlIHJlbW92ZWQgb25lIGJ5IG9uZSBhbmQgdGhlIG1vZGVscyBhcmUgY29tcGFyZWQgYWNjb3JkaW5nIHRvIEFJQyB2YWx1ZXMuIFRoZSBsb3dlcyBBSUMgdmFsdWUgbW9kZWwgaXM6IGZpdC53Lm8ubXVsYWthdC4gVGhpcyBpcyB0aGUgbW9kZWwgdGhhdCBkb2Vzbid0IGNvbnRhaW4gdGhlIGtleXdvcmQgIk3DvGxha2F0Ii4gU28gb3VyIGZpbmFsIG1vZGVsIGlzIGNob3NlbiBhbmQgdGhlIHJlc2lkdWFsIGFuYWx5c2lzIHdpbGwgYmUgcHJvY2VlZGVkIGFjY29yZGluZ2x5LgoKYGBge3J9CmZpdC5ldmVyeXRoaW5nIDwtIHRzbG0odW5lbXBsb3ltZW50X3RzIH4gdCArIAogICAgICAgICAgICAgICAgICAgICAgICB0YjEgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGIyICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHNlYXNvbmFsZHVtbXkodW5lbXBsb3ltZW50X3RzKSArIAogICAgICAgICAgICAgICAgICAgICAgICBrcmVkaV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICBpc19pbGFuaV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICBpc3Npemxpa190cyArIAogICAgICAgICAgICAgICAgICAgICAgICBtdWxha2F0X3RzKQoKZml0Lncuby5rcmVkaSA8LSB0c2xtKHVuZW1wbG95bWVudF90cyB+IHQgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGIxICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRiMiArIAogICAgICAgICAgICAgICAgICAgICAgICBzZWFzb25hbGR1bW15KHVuZW1wbG95bWVudF90cykgKyAKICAgICAgICAgICAgICAgICAgICAgICAgaXNfaWxhbmlfdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgaXNzaXpsaWtfdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgbXVsYWthdF90cykKCmZpdC53Lm8uaXNfaWxhbmkgPC0gdHNsbSh1bmVtcGxveW1lbnRfdHMgfiB0ICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRiMSArIAogICAgICAgICAgICAgICAgICAgICAgICB0YjIgKyAKICAgICAgICAgICAgICAgICAgICAgICAgc2Vhc29uYWxkdW1teSh1bmVtcGxveW1lbnRfdHMpICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGtyZWRpX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGlzc2l6bGlrX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIG11bGFrYXRfdHMpCgpmaXQudy5vLmlzc2l6bGlrIDwtIHRzbG0odW5lbXBsb3ltZW50X3RzIH4gdCArIAogICAgICAgICAgICAgICAgICAgICAgICB0YjEgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGIyICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHNlYXNvbmFsZHVtbXkodW5lbXBsb3ltZW50X3RzKSArIAogICAgICAgICAgICAgICAgICAgICAgICBrcmVkaV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICBpc19pbGFuaV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICBtdWxha2F0X3RzKQoKZml0Lncuby5tdWxha2F0IDwtIHRzbG0odW5lbXBsb3ltZW50X3RzIH4gdCArIAogICAgICAgICAgICAgICAgICAgICAgICB0YjEgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGIyICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHNlYXNvbmFsZHVtbXkodW5lbXBsb3ltZW50X3RzKSArIAogICAgICAgICAgICAgICAgICAgICAgICBrcmVkaV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICBpc19pbGFuaV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICBpc3Npemxpa190cykKCmFsbCA8LSBDVihmaXQuZXZlcnl0aGluZykKbm9fa3JlZGkgPC0gQ1YoZml0Lncuby5rcmVkaSkKbm9faXNfaWxhbmkgPC0gQ1YoZml0Lncuby5pc19pbGFuaSkKbm9faXNzaXpsaWsgPC0gQ1YoZml0Lncuby5pc3NpemxpaykKbm9fbXVsYWthdCA8LSBDVihmaXQudy5vLm11bGFrYXQpCkNWX2RhdGEgPC0gZGF0YS5mcmFtZShyYmluZChhbGwsIG5vX2tyZWRpLCBub19pc19pbGFuaSwgbm9zX2lzc2l6bGlrLCBub19tdWxha2F0KSkKQ1ZfZGF0YQpgYGAKClRoZSBtb2RlbCBhbmQgdGhlIGRhdGEgYXJlIHBsb3R0ZWQgaW4gb3JkZXIgdG8gc2VlIHZpc3VhbGx5IGhvdyB0aGV5IGJlaGF2ZS4KCmBgYHtyfQphdXRvcGxvdCh1bmVtcGxveW1lbnRfdHMsIHNlcmllcyA9ICJEYXRhIikgKyAKICBhdXRvbGF5ZXIoZml0dGVkKGZpdC53Lm8ubXVsYWthdCksIHNlcmllcyA9ICJNb2RlbCIpCmBgYAoKRnJvbSB0aGUgcmVzaWR1YWwgYW5hbHlzaXMgcGFydCB3ZSBjYW4gY29uY2x1ZGUgdGhhdDoKCi0gICBUaGUgcmVzaWR1YWxzIHNlZW0gdG8gaGF2ZSBtZWFuIHplcm8gYW5kIHRoZW0gc2VlbSB0byBiZSBub3JtYWxseSBkaXN0cmlidXRlZC4KLSAgIEhvd2V2ZXIgdGhleSBzaG93IGluY3JlYXNpbmcgQUMgZXNwZWNpYWxseSBhdCBsYWdzIDEyLDI0IGFuZCAzNi4gVGhlcmVmb3JlIHdlIGNhbiBkZWR1Y3QgdGhhdCB0aGVyZSBpcyBtb3JlIGluZm9ybWF0aW9uIGxlZnQgb3V0IGVzcGVjaWFsbHkgaW4gc2Vhc29uYWxpdHkgdGVybXMuCgpXaGVuIGNvbnNpZGVyaW5nIGRpZmZlcmVudCBwcmVkaWN0b3JzIHdlIGNhbiBvYnNlcnZlIHRoYXQgSmFudWFyeSwgRmVicnVhcnkgYW5kIE1hcmNoIHNlYXNvbmFsIHZhcmlhYmxlcyBhcmUgYWN0dWFsbHkgbm90IHZlcnkgaW50dWl0aXZlIGFzIHRoZXkgaGF2ZSBoaWdoIHAtdmFsdWVzLgoKV2hlbiB0aGUgUmVzaWR1YWxzIHZzLiBGaXR0ZWQgdmFsdWVzIGdyYXBoIGlzIG9ic2VydmVkLCBpdCBjYW4gYmUgc2VlbiB0aGF0CgpPdmVyYWxsLCB0aGUgbW9kZWwgc2VlbXMgdG8gYmUgYWRlcXVhdGUsIGhvd2V2ZXIgdGhlcmUgYXJlIHBhcnRzIHRvIGltcHJvdmUgdGhlIG1vZGVsLCBlc3BlY2lhbGx5IGluIHNlYXNvbmFsaXR5IHRlcm1zLgoKYGBge3J9CmNoZWNrcmVzaWR1YWxzKGZpdC53Lm8ubXVsYWthdCkKc3VtbWFyeShmaXQudy5vLm11bGFrYXQpCgpyZXNpZHVhbF9maXR0ZWQgPC0gZGF0YS5mcmFtZShjYmluZChGaXR0ZWQgPSBmaXR0ZWQoZml0Lncuby5tdWxha2F0KSwgUmVzaWR1YWxzPXJlc2lkdWFscyhmaXQudy5vLm11bGFrYXQpKSkKZ2dwbG90KHJlc2lkdWFsX2ZpdHRlZCwgYWVzKHggPSBGaXR0ZWQsIHkgPSBSZXNpZHVhbHMpKSArIGdlb21fcG9pbnQoKSArIGdndGl0bGUoIlJlc2lkdWFscyB2cy4gRml0dGVkIFZhbHVlcyIpCmBgYAoKIyMgSG91c2UgUHJpY2UgSW5kZXgKCkluIG9yZGVyIHRvIGdldCBhIG1vcmUgcmVhbCBIb3VzZSBQcmljZSBJbmRleCwgdGhlIGRhdGEgaXMgZGl2aWRlZCB0byBVUyBkb2xsYXIgaW4gb3JkZXIgdG8gZ2V0IHRoZSBxdWFudGl0aWVzIGluIGRvbGxhcnMuCgpTZWFzb25hbGl0eSBjYW4gYmUgb2JzZXJ2ZWQgZXNwZWNpYWxseSBhdCB0aGUgdGltZSBiZXR3ZWVuIDIwMTQgYW5kIDIwMTguCgpUaGVyZSBpcyBhIGNsZWFyIGRvd253YXJkIHRyZW5kIGZyb20gMjAxNCB0byAyMDE4IGFuZCBhbiB1cHdhcmQgdHJlbmQgZnJvbSAyMDIyIHRvIDIwMjQuCgpgYGB7cn0KdGltZV9kYXRhX2hvdXNlIDwtIGMoeWVhcihtaW4oaG91c2VfaW5kZXhfZGF0YSRUYXJpaCkpLCBtb250aChtaW4oaG91c2VfaW5kZXhfZGF0YSRUYXJpaCkpKQoKZG9sbGFyX2RhdGFwYXRoID0gJy9Vc2Vycy9haG1ldGthcmFrb3NlL0Rlc2t0b3AvZG9sYXIueGxzeCcKZG9sbGFyX2RhdGEgPSByZWFkX2V4Y2VsKGRvbGxhcl9kYXRhcGF0aCkKZG9sbGFyX2RhdGEgPC0gZG9sbGFyX2RhdGFbLSgxMjI6MTMzKSxdCmRvbGxhcl9kYXRhIDwtIGRvbGxhcl9kYXRhWywtM10KZG9sbGFyX2RhdGEkIlRQIERLIFVTRCBBIFlUTCIgIDwtIGFzLm51bWVyaWMoZG9sbGFyX2RhdGEkIlRQIERLIFVTRCBBIFlUTCIpCm5hbWVzKGRvbGxhcl9kYXRhKVtuYW1lcyhkb2xsYXJfZGF0YSkgPT0gIlRQIERLIFVTRCBBIFlUTCJdIDwtICJEb2xsYXIiCmRvbGxhcl9kYXRhJFRhcmloIDwtIHBhc3RlKGRvbGxhcl9kYXRhJFRhcmloLCAiLTAxIiwgc2VwID0gIiIpCmRvbGxhcl9kYXRhJFRhcmloIDwtIGFzLkRhdGUoZG9sbGFyX2RhdGEkVGFyaWgpCgpob3VzZV9pbmRleF9kYXRhWywyXSA8LSBob3VzZV9pbmRleF9kYXRhWywyXSAvIGRvbGxhcl9kYXRhWywyXQoKaG91c2VfaW5kZXhfdHMgPC0gdHMoaG91c2VfaW5kZXhfZGF0YSRgSG91c2UgUHJpY2UgSW5kZXhgLCBzdGFydCA9IHRpbWVfZGF0YSwgZnJlcXVlbmN5ID0gMTIpCgphdXRvcGxvdChob3VzZV9pbmRleF90cykgKyBnZ3RpdGxlKCJIb3VzZSBQcmljZSBJbmRleCB2cyBUaW1lIikgKyB4bGFiKCJZZWFyIikgKyB5bGFiKCJIb3VzZSBJbmRleCAyMDE3ID0gMTAwIikKYGBgCgpMZXQncyBsb29rIGF0IHRoZSBhdXRvY29ycmVsYXRpb24gZnVuY3Rpb24gb2YgdGhlIHRpbWUgc2VyaWVzIGluIG9yZGVyIHRvIGNoZWNrIHNlYXNvbmFsaXR5LiBUaGUgQUNGIGRvZXMgbm90IHNob3cgYW55IGNsZWFyIHBhdHRlcm4gb2Ygc2Vhc29uYWxpdHkgaW4gdGhpcyBjYXNlLgoKYGBge3J9CkFjZihob3VzZV9pbmRleF90cywgbGFnLm1heCA9IDI0KQpgYGAKCk5vdywgd2Ugd2FudCB0byBmaW5kIHByZWRpY3RvcnMgZnJvbSBHb29nbGUgVHJlbmRzIHRoYXQgY2FuIGJlIHNvbWVob3cgcmVsYXRlZCB3aXRoIHRoZSBIb3VzZSBQcmljZSBJbmRleCBpbiBUdXJrZXkuIFdoZW4ga2V5d29yZHMgZm9yIHRoaXMgcmVsYXRpb24gaXMgdGhvdWdodCBmb3IsIHRoZXNlIGtleXdvcmRzIGFyZSBmb3VuZCB0byBiZSBsb2dpY2FsIGFuZCByZWxhdGVkIHdpdGggSG91c2UgUHJpY2UgSW5kZXg6CgotICAgIlNhdMSxbMSxayBkYWlyZSI6IE9idmlvdXNseSB0aGlzIGtleXdvcmQgbWF5IGJlIGEgZ29vZCBwcmVkaWN0b3IgZm9yIEhvdXNlIFByaWNlIEluZGV4Ci0gICAiRmFpeiI6IEludGVyZXN0IHJhdGVzIG1heSBpbmNyZWFzZSBjcmVkaXQgcmF0ZXMgZm9yIGhvdXNlcyBhcyB3ZWxsLiBUaGlzIG1heSBoYXZlIGEgcmVsYXRpb24gd2l0aCBIb3VzZSBQcmljZSBJbmRleC4KLSAgICJFbWxhayI6IE9idmlvdXNseSB0aGlzIGtleXdvcmQgbWF5IGJlIGEgZ29vZCBwcmVkaWN0b3IgZm9yIEhvdXNlIFByaWNlIEluZGV4Ci0gICAixLBwb3RlayIKCkl0IHNob3VsZCBiZSBub3RlZCB0aGF0IG1heWJlIHRoZSBsYWdnZWQgdmFsdWVzIG9mIHRoZXNlIGRhdGEgY2FuIGJlIGJldHRlciBwcmVkaWN0b3JzIGJlY2F1c2UsIHBlb3BsZSBtYXkgc2VhcmNoIHRoZXNlIHRlcm1zIGFmdGVyIHRoZSBIb3VzZSBQcmljZSBJbmRleCBpbmNyZWFzZXMuIFRoZXNlIHNlYXJjaCB0ZXJtcyBhcmUgcmVzdWx0cywgc28gdGhlIGFmZmVjdHMgb2YgdGhlc2Ugc2VhcmNoIHRlcm1zIG1heSBiZSBkZWxheWVkLgoKQmVsb3cgYWxsIG9mIHRoZSBkYXRhIGlzIGdhdGhlcmVkIGFuZCB0aW1lIHNlcmllcyBvYmplY3RzIGFyZSBmb3JtZWQuIEFsbCBwb3RlbnRpYWwgcHJlZGljdG9yIGRhdGEgYXJlIHBsb3R0ZWQgYW5kIGEgY29tYmluYXRpb24gb2YgdGhlIHBvdGVudGlhbCBwcmVkaWN0b3JzIGFyZSBjb21iaW5lZC4gVGhlc2UgcHJlZGljdG9ycyBhcmUgYWxzbyBjb21iaW5lZCB3aXRoaW4gYW5vdGhlciBkYXRhIGZyYW1lLgoKYGBge3J9CnNhdGlsaWtfZGFpcmUgPSBmcmVhZCgiL1VzZXJzL2FobWV0a2FyYWtvc2UvRGVza3RvcC9zYXRpbGlrX2RhaXJlLmNzdiIpCm5hbWVzKHNhdGlsaWtfZGFpcmUpW25hbWVzKHNhdGlsaWtfZGFpcmUpID09ICJzYXTEsWzEsWsgZGFpcmU6IChUw7xya2l5ZSkiXSA8LSAiU2F0xLFsxLFrIGRhaXJlIgpzYXRpbGlrX2RhaXJlX3RzIDwtIHRzKHNhdGlsaWtfZGFpcmVbLC0xXSwgc3RhcnQgPSB0aW1lX2RhdGEsIGZyZXF1ZW5jeSA9IDEyKQoKZmFpeiA9IGZyZWFkKCIvVXNlcnMvYWhtZXRrYXJha29zZS9EZXNrdG9wL2ZhaXouY3N2IikKbmFtZXMoZmFpeilbbmFtZXMoZmFpeikgPT0gImZhaXo6IChUw7xya2l5ZSkiXSA8LSAiRmFpeiIKZmFpel90cyA8LSB0cyhmYWl6WywtMV0sIHN0YXJ0ID0gdGltZV9kYXRhLCBmcmVxdWVuY3kgPSAxMikKCmVtbGFrID0gZnJlYWQoIi9Vc2Vycy9haG1ldGthcmFrb3NlL0Rlc2t0b3AvZW1sYWsuY3N2IikKbmFtZXMoZW1sYWspW25hbWVzKGVtbGFrKSA9PSAiZW1sYWs6IChUw7xya2l5ZSkiXSA8LSAiRW1sYWsiCmVtbGFrX3RzIDwtIHRzKGVtbGFrWywtMV0sIHN0YXJ0ID0gdGltZV9kYXRhLCBmcmVxdWVuY3kgPSAxMikKCmlwb3RlayA9IGZyZWFkKCIvVXNlcnMvYWhtZXRrYXJha29zZS9EZXNrdG9wL2lwb3Rlay5jc3YiKQpuYW1lcyhpcG90ZWspW25hbWVzKGlwb3RlaykgPT0gImlwb3RlazogKFTDvHJraXllKSJdIDwtICLEsHBvdGVrIgppcG90ZWtfdHMgPC0gdHMoaXBvdGVrWywtMV0sIHN0YXJ0ID0gdGltZV9kYXRhLCBmcmVxdWVuY3kgPSAxMikKCmF1dG9wbG90KHNhdGlsaWtfZGFpcmVfdHMpCmF1dG9wbG90KGZhaXpfdHMpCmF1dG9wbG90KGVtbGFrX3RzKQphdXRvcGxvdChpcG90ZWtfdHMpCgoKcHJlZGljdG9yc19ocF9pbmRleCA8LSBjYmluZChzYXRpbGlrX2RhaXJlWywtMV0sIGZhaXpbLC0xXSwgZW1sYWtbLC0xXSwgaXBvdGVrWywtMV0pCmRmX2hwX2luZGV4IDwtIGNiaW5kKGhvdXNlX2luZGV4X2RhdGEsIHByZWRpY3RvcnNfaHBfaW5kZXgpCmBgYAoKQmVsb3cgaXMgdGhlIGNvcnJlbGF0aW9ucyBiZXR3ZWVuIGVhY2ggcHJlZGljdG9ycyBhbmQgdGhlIGZvcmVjYXN0IHZhcmlhYmxlLiBUaGUgcmVsYXRpb25zIG9mIGVhY2ggb2YgdGhlbSBjYW4gYmUgb2JzZXJ2ZWQgYmVsb3cuCgpgYGB7cn0KcmVxdWlyZShHR2FsbHkpCmdncGFpcnMoZGZfaHBfaW5kZXhbLC0xXSkKYGBgCgpOb3csIGl0J3MgdGltZSB0byBjcmVhdGUgdGhlIG1vZGVsLiBGaXJzdGx5IHRoZSBsYWdnZWQgZGF0YSBmcmFtZXMgZm9yIGFsbCBvZiB0aGUgc2VsZWN0ZWQgcHJlZGljdG9ycyBhcmUgY3JlYXRlZCAoR29vZ2xlIHRyZW5kcyBkYXRhKS4gVGhpcyBpcyB0byBjb21wYXJlIHRoZSBsYWdnZWQgbW9kZWxzIHdpdGhvdXQgdGhlIGxhZ2dlZCBtb2RlbC4gVGhlbiB0aGUgcGllY2Ugd2lzZSBsaW5lYXIgdHJlbmQgaXMgZm9ybWVkLiBUaHJlZSBwb3NzaWJsZSBtb2RlbHMgYXJlIGNyZWF0ZWQ6CgotICAgZml0OiBVc2luZyBhbGwgdGhlIHByZWRpY3RvcnMKLSAgIGZpdC5sYWcxOiBVc2luZyBhbGwgdGhlIGxhZy0xIHByZWRpY3RvcnMKLSAgIGZpdC5sYWcyOiBVc2luZyBhbGwgdGhlIGxhZy0yIHByZWRpY3RvcnMKClRoZSBiZXN0IG9uZSB3aWxsIGJlIGV2YWx1YXRlZCBiYXNlZCBvbiB0aGUgbG93ZXN0IEFJQyB2YWx1ZS4gQXMgaXQgY2FuIGJlIHNlZW4gYmVsb3csIHRoZSBsb3dlc3QgQUlDIHZhbHVlIGlzIHRoZSBvbmUgd2l0aCBsYWctMS4gV2Ugd2lsbCBwcm9jZWVkIHdpdGggdGhpcyBtb2RlbCBpbiB0aGUgdXBjb21pbmcgY29tcGFyaXNvbnMuCgpgYGB7cn0KCmxpYnJhcnkoZHBseXIpCnNhdGlsaWtfZGFpcmVfbGFnIDwtIG11dGF0ZShzYXRpbGlrX2RhaXJlLAogICAgICAgICAgICAgICBzYXRpbGlrX2RhaXJlX2xhZzEgPSBsYWcoc2F0aWxpa19kYWlyZSRgU2F0xLFsxLFrIGRhaXJlYCwgMSksICAjIExhZyAxCiAgICAgICAgICAgICAgIHNhdGlsaWtfZGFpcmVfbGFnMiA9IGxhZyhzYXRpbGlrX2RhaXJlJGBTYXTEsWzEsWsgZGFpcmVgLCAyKSwgICMgTGFnIDIKICAgICAgICAgICAgICAgKQoKZmFpel9sYWcgPC0gbXV0YXRlKGZhaXosCiAgICAgICAgICAgICAgIGZhaXpfbGFnMSA9IGxhZyhmYWl6JEZhaXosIDEpLCAgIyBMYWcgMQogICAgICAgICAgICAgICBmYWl6X2xhZzIgPSBsYWcoZmFpeiRGYWl6LCAyKSwgICMgTGFnIDIKICAgICAgICAgICAgICAgKQoKZW1sYWtfbGFnIDwtIG11dGF0ZShlbWxhaywKICAgICAgICAgICAgICAgZW1sYWtfbGFnMSA9IGxhZyhlbWxhayRFbWxhaywgMSksICAjIExhZyAxCiAgICAgICAgICAgICAgIGVtbGFrX2xhZzIgPSBsYWcoZW1sYWskRW1sYWssIDIpLCAgIyBMYWcgMgogICAgICAgICAgICAgICApCgppcG90ZWtfbGFnIDwtIG11dGF0ZShpcG90ZWssCiAgICAgICAgICAgICAgIGlwb3Rla19sYWcxID0gbGFnKGlwb3RlayTEsHBvdGVrLCAxKSwgICMgTGFnIDEKICAgICAgICAgICAgICAgaXBvdGVrX2xhZzIgPSBsYWcoaXBvdGVrJMSwcG90ZWssIDIpLCAgIyBMYWcgMgogICAgICAgICAgICAgICApCgpjb21iaW5lZF9sYWcgPC0gY2JpbmQoc2F0aWxpa19kYWlyZV9sYWcsIGZhaXpfbGFnLCBlbWxha19sYWcsIGlwb3Rla19sYWcpCgp0IDwtIHRpbWUodW5lbXBsb3ltZW50X3RzKQp0LmJyZWFrMSA8LSAyMDE4CnQuYnJlYWsyIDwtIDIwMjIKdGIxIDwtIHRzKHBtYXgoMCwgdCAtIHQuYnJlYWsxKSwgc3RhcnQgPSAyMDE0LCBlbmQgPSAyMDI0LCBmcmVxdWVuY3kgPSAxMikKdGIyIDwtIHRzKHBtYXgoMCwgdC0gdC5icmVhazIpLCBzdGFydCA9IDIwMTQsIGVuZCA9IDIwMjQsIGZyZXF1ZW5jeSA9IDEyKQoKZml0IDwtIHRzbG0oaG91c2VfaW5kZXhfdHMgfiBzYXRpbGlrX2RhaXJlX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGZhaXpfdHMrIAogICAgICAgICAgICAgICAgICAgICAgICBlbWxha190cyArCiAgICAgICAgICAgICAgICAgICAgICAgIGlwb3Rla190cyArIAogICAgICAgICAgICAgICAgICAgICAgICB0ICsKICAgICAgICAgICAgICAgICAgICAgICAgdGIxICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRiMikKCmZpdC5sYWcxIDwtIHRzbG0oaG91c2VfaW5kZXhfdHMgfiB0ICsKICAgICAgICAgICAgICAgICAgICAgICAgdGIxICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRiMiArIAogICAgICAgICAgICAgICAgICAgICAgICBzYXRpbGlrX2RhaXJlX2xhZzEgKyAKICAgICAgICAgICAgICAgICAgICAgICAgZmFpel9sYWcxICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGVtbGFrX2xhZzEgKwogICAgICAgICAgICAgICAgICAgICAgICBpcG90ZWtfbGFnMSwgZGF0YSA9IGNvbWJpbmVkX2xhZykKCmZpdC5sYWcyIDwtIHRzbG0oaG91c2VfaW5kZXhfdHMgfiB0ICsKICAgICAgICAgICAgICAgICAgICAgICAgdGIxICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRiMiArIAogICAgICAgICAgICAgICAgICAgICAgICBzYXRpbGlrX2RhaXJlX2xhZzIgKyAKICAgICAgICAgICAgICAgICAgICAgICAgZmFpel9sYWcyICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGVtbGFrX2xhZzIgKwogICAgICAgICAgICAgICAgICAgICAgICBpcG90ZWtfbGFnMiwgZGF0YSA9IGNvbWJpbmVkX2xhZykgCgoKbm9fbGFnIDwtIENWKGZpdCkKbGFnXzEgPC0gQ1YoZml0LmxhZzEpCmxhZ18yIDwtIENWKGZpdC5sYWcyKQpDVl9kYXRhIDwtIGRhdGEuZnJhbWUocmJpbmQobm9fbGFnLCBsYWdfMSwgbGFnXzIpKQpDVl9kYXRhCmBgYAoKTm93LCB3ZSB3aWxsIGluc3BlY3QgdGhlIG1vZGVsIGZ1cnRoZXIgYW5kIHRyeSB0byByZW1vdmUgdGhlIHVubmVjZXNzYXJ5IHByZWRpY3Rvci4gSW4gdGhpcyBjYXNlIGFsbCBvZiB0aGUgcHJlZGljdG9ycyAoR29vZ2xlIHRyZW5kcyBkYXRhKSBhcmUgcmVtb3ZlZCBvbmUgYnkgb25lIGFuZCB0aGUgbW9kZWxzIGFyZSBjb21wYXJlZCBhY2NvcmRpbmcgdG8gQUlDIHZhbHVlcy4gVGhlIGxvd2VzdCBBSUMgdmFsdWUgbW9kZWwgaXM6IGZpdC53Lm8uZW1sYWsuIFRoaXMgaXMgdGhlIG1vZGVsIHRoYXQgZG9lc24ndCBjb250YWluIHRoZSBrZXl3b3JkICJFbWxhayIuIFNvIG91ciBmaW5hbCBtb2RlbCBpcyBjaG9zZW4gYW5kIHRoZSByZXNpZHVhbCBhbmFseXNpcyB3aWxsIGJlIHByb2NlZWRlZCBhY2NvcmRpbmdseS4KCmBgYHtyfQpmaXQuZXZlcnl0aGluZyA8LSB0c2xtKGhvdXNlX2luZGV4X3RzIH4gdCArCiAgICAgICAgICAgICAgICAgICAgICAgIHRiMSArIAogICAgICAgICAgICAgICAgICAgICAgICB0YjIgKyAKICAgICAgICAgICAgICAgICAgICAgICAgc2F0aWxpa19kYWlyZV9sYWcxICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGZhaXpfbGFnMSArIAogICAgICAgICAgICAgICAgICAgICAgICBlbWxha19sYWcxICsKICAgICAgICAgICAgICAgICAgICAgICAgaXBvdGVrX2xhZzEsIGRhdGEgPSBjb21iaW5lZF9sYWcpCgpmaXQudy5vLnNhdGlsaWtfZGFpcmUgPC0gdHNsbShob3VzZV9pbmRleF90cyB+IHQgKwogICAgICAgICAgICAgICAgICAgICAgICB0YjEgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGIyICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGZhaXpfbGFnMSArIAogICAgICAgICAgICAgICAgICAgICAgICBlbWxha19sYWcxICsKICAgICAgICAgICAgICAgICAgICAgICAgaXBvdGVrX2xhZzEsIGRhdGEgPSBjb21iaW5lZF9sYWcpCgpmaXQudy5vLmZhaXogPC0gdHNsbShob3VzZV9pbmRleF90cyB+IHQgKwogICAgICAgICAgICAgICAgICAgICAgICB0YjEgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGIyICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHNhdGlsaWtfZGFpcmVfbGFnMSArIAogICAgICAgICAgICAgICAgICAgICAgICBlbWxha19sYWcxICsKICAgICAgICAgICAgICAgICAgICAgICAgaXBvdGVrX2xhZzEsIGRhdGEgPSBjb21iaW5lZF9sYWcpCgpmaXQudy5vLmVtbGFrIDwtIHRzbG0oaG91c2VfaW5kZXhfdHMgfiB0ICsKICAgICAgICAgICAgICAgICAgICAgICAgdGIxICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRiMiArIAogICAgICAgICAgICAgICAgICAgICAgICBzYXRpbGlrX2RhaXJlX2xhZzEgKyAKICAgICAgICAgICAgICAgICAgICAgICAgZmFpel9sYWcxICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGlwb3Rla19sYWcxLCBkYXRhID0gY29tYmluZWRfbGFnKQoKZml0Lncuby5pcG90ZWsgPC0gdHNsbShob3VzZV9pbmRleF90cyB+IHQgKwogICAgICAgICAgICAgICAgICAgICAgICB0YjEgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGIyICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHNhdGlsaWtfZGFpcmVfbGFnMSArIAogICAgICAgICAgICAgICAgICAgICAgICBmYWl6X2xhZzEgKyAKICAgICAgICAgICAgICAgICAgICAgICAgZW1sYWtfbGFnMSwgZGF0YSA9IGNvbWJpbmVkX2xhZykKCmFsbCA8LSBDVihmaXQuZXZlcnl0aGluZykKbm9fc2F0aWxpa19kYWlyZSA8LSBDVihmaXQudy5vLnNhdGlsaWtfZGFpcmUpCm5vX2ZhaXogPC0gQ1YoZml0Lncuby5mYWl6KQpub19lbWxhayA8LSBDVihmaXQudy5vLmVtbGFrKQpub19pcG90ZWsgPC0gQ1YoZml0Lncuby5pcG90ZWspCkNWX2RhdGEgPC0gZGF0YS5mcmFtZShyYmluZChhbGwsIG5vX3NhdGlsaWtfZGFpcmUsIG5vX2ZhaXosIG5vX2VtbGFrLCBub19pcG90ZWspKQpDVl9kYXRhCmBgYApUaGUgbW9kZWwgYW5kIHRoZSBkYXRhIGFyZSBwbG90dGVkIGluIG9yZGVyIHRvIHNlZSB2aXN1YWxseSBob3cgdGhleSBiZWhhdmUuCgpgYGB7cn0KYXV0b3Bsb3QoaG91c2VfaW5kZXhfdHMsIHNlcmllcyA9ICJEYXRhIikgKyAKICBhdXRvbGF5ZXIoZml0dGVkKGZpdC53Lm8uZW1sYWspLCBzZXJpZXMgPSAiTW9kZWwiKQpgYGAKRnJvbSB0aGUgcmVzaWR1YWwgYW5hbHlzaXMgcGFydCB3ZSBjYW4gY29uY2x1ZGUgdGhhdDoKCi0gICBUaGUgcmVzaWR1YWxzIHNlZW0gdG8gaGF2ZSBtZWFuIHplcm8gYW5kIHRoZW0gc2VlbSB0byBiZSBub3JtYWxseSBkaXN0cmlidXRlZC4KLSAgIEhvd2V2ZXIgdGhleSBzaG93IGluY3JlYXNpbmcgQUMgZXNwZWNpYWxseSBhdCBsYWdzIDEsMiwxMiwxOCwzMC4gVGhlcmVmb3JlIHdlIGNhbiBkZWR1Y3QgdGhhdCB0aGVyZSBpcyBtb3JlIGluZm9ybWF0aW9uIGxlZnQgb3V0LgoKV2hlbiBjb25zaWRlcmluZyBkaWZmZXJlbnQgcHJlZGljdG9ycyB3ZSBjYW4gb2JzZXJ2ZSB0aGF0IHRiMSB2YXJpYWJsZSBpcyBhY3R1YWxseSBub3QgdmVyeSBpbnR1aXRpdmUgYXMgaXQgaGFzIGEgdmVyeSBoaWdoIHAtdmFsdWUuCgpXaGVuIHRoZSBSZXNpZHVhbHMgdnMuIEZpdHRlZCB2YWx1ZXMgZ3JhcGggaXMgb2JzZXJ2ZWQsIGl0IGNhbiBiZSBzZWVuIHRoYXQgdGhlIHJlc2lkdWFscyBhcmUga2luZCBvZiBzY2F0dGVyZWQgYXJvdW5kIAoKT3ZlcmFsbCwgdGhlIG1vZGVsIHNlZW1zIHRvIGJlIGFkZXF1YXRlLCBob3dldmVyIHRoZXJlIGFyZSBwYXJ0cyB0byBpbXByb3ZlIHRoZSBtb2RlbCwgZXNwZWNpYWxseSBpbiB0cmVuZCB0ZXJtcy4KCmBgYHtyfQpzdW1tYXJ5KGZpdC53Lm8uZW1sYWspCmNoZWNrcmVzaWR1YWxzKGZpdC53Lm8uZW1sYWspCgpyZXNpZHVhbF9maXR0ZWQgPC0gZGF0YS5mcmFtZShjYmluZChGaXR0ZWQgPSBmaXR0ZWQoZml0Lncuby5lbWxhayksIFJlc2lkdWFscz1yZXNpZHVhbHMoZml0Lncuby5lbWxhaykpKQpnZ3Bsb3QocmVzaWR1YWxfZml0dGVkLCBhZXMoeCA9IEZpdHRlZCwgeSA9IFJlc2lkdWFscykpICsgZ2VvbV9wb2ludCgpICsgZ2d0aXRsZSgiUmVzaWR1YWxzIHZzLiBGaXR0ZWQgVmFsdWVzIikKYGBgCiMjIFJlYWwgU2VjdG9yIENvbmZpZGVuY2UKCkxhc3RseSwgdGhlIHJlZ3Jlc3Npb24gbW9kZWwgZm9yIHRoZSBSZWFsIFNlY3RvciBDb25maWRlbmNlIGRhdGEgd2lsbCBiZSBidWlsdC4KCkJlbG93IGlzIHRoZSBSZWFsIFNlY3RvciBDb25maWRlbmNlIHZzLiBUaW1lIGdyYXBoLiBXZSBjYW4gbWFrZSBzb21lIGRlZHVjdGlvbnMgb3V0IG9mIGl0OgoKLSAgIFRoZXJlIHNlZW1zIHRvIGJlIHNlYXNvbmFsaXR5IGVzcGVjaWFsbHkgYmV0d2VlbiAyMDE0LTIwMTguCi0gICBUaGVyZSBzZWVtcyB0byBiZSBubyB0cmVuZAotICAgVGhlcmUgaXMgYSBzaGFycCBkZWNyZWFzZSBpbiAyMDIwIE1hcmNoLCBtb3N0IHByb2JhYmx5IGR1ZSB0byB0aGUgY29yb25hLXZpcnVzLgoKYGBge3J9CmNvbmZpZGVuY2VfdHMgPC0gdHMoY29uZmlkZW5jZSQiUmVhbCBTZWN0b3IgQ29uZmlkZW5jZSBJbmRleCIsIHN0YXJ0ID0gdGltZV9kYXRhLCBmcmVxdWVuY3kgPSAxMikKZGF0YS5mcmFtZShjb25maWRlbmNlX3RzKQoKYXV0b3Bsb3QoY29uZmlkZW5jZV90cykgKyBnZ3RpdGxlKCJSZWFsIFNlY3RvciBDb25maWRlbmNlIHZzIFRpbWUiKSArIHhsYWIoIlllYXIiKSArIHlsYWIoIkNvbmZpZGVuY2UiKQpgYGAKTGV0J3MgbG9vayBhdCB0aGUgYXV0b2NvcnJlbGF0aW9uIGZ1bmN0aW9uIG9mIHRoZSB0aW1lIHNlcmllcyBpbiBvcmRlciB0byBjaGVjayBzZWFzb25hbGl0eS4gVGhlIEFDRiBkb2VzIG5vdCBzaG93IGFueSBjbGVhciBwYXR0ZXJuIG9mIHNlYXNvbmFsaXR5IGluIHRoaXMgY2FzZS4KCmBgYHtyfQpnZ0FjZihjb25maWRlbmNlX3RzLCBsYWcubWF4ID0gNDgpCmBgYApOb3csIHdlIHdhbnQgdG8gZmluZCBwcmVkaWN0b3JzIGZyb20gR29vZ2xlIFRyZW5kcyB0aGF0IGNhbiBiZSBzb21laG93IHJlbGF0ZWQgd2l0aCB0aGUgUmVhbCBTZWN0b3IgQ29uZmlkZW5jZSBpbiBUdXJrZXkuIFdoZW4ga2V5d29yZHMgZm9yIHRoaXMgcmVsYXRpb24gaXMgdGhvdWdodCBmb3IsIHRoZXNlIGtleXdvcmRzIGFyZSBmb3VuZCB0byBiZSBsb2dpY2FsIGFuZCByZWxhdGVkIHdpdGggUmVhbCBTZWN0b3IgQ29uZmlkZW5jZQoKLSAgICJGYWl6IjogSW5jcmVhc2UgaW4gaW50ZXJlc3QgcmF0ZXMgbWF5IGJlIGEgYmFkIHNpZ24gZm9yIGNvbmZpZGVuY2UKLSAgICJUaWNhcmV0IjogSW5jcmVhc2UgaW4gdHJhZGUgbWF5IG1lYW4gbW9yZSBjb25maWRlbmNlCi0gICAiVXJldGltIjogSW5jcmVhc2UgaW4gcHJvZHVjdGlvbiBtYXkgbWVhbiBtb3JlIGNvbmZpZGVuY2UKLSAgICLEsHN0aWhkYW0iOiBJbmNyZWFzZSBpbiBlbXBsb3ltZW50IG1heSBtZWFuIG1vcmUgY29uZmlkZW5jZQoKSXQgc2hvdWxkIGJlIG5vdGVkIHRoYXQgbWF5YmUgdGhlIGxhZ2dlZCB2YWx1ZXMgb2YgdGhlc2UgZGF0YSBjYW4gYmUgYmV0dGVyIHByZWRpY3RvcnMgYmVjYXVzZSwgcGVvcGxlIG1heSBzZWFyY2ggdGhlc2UgdGVybXMgYWZ0ZXIgdGhlIFJlYWwgU2VjdG9yIENvbmZpZGVuY2UgY2hhbmdlcyBUaGVzZSBzZWFyY2ggdGVybXMgYXJlIHJlc3VsdHMsIHNvIHRoZSBhZmZlY3RzIG9mIHRoZXNlIHNlYXJjaCB0ZXJtcyBtYXkgYmUgZGVsYXllZC4KCkJlbG93IGFsbCBvZiB0aGUgZGF0YSBpcyBnYXRoZXJlZCBhbmQgdGltZSBzZXJpZXMgb2JqZWN0cyBhcmUgZm9ybWVkLiBBbGwgcG90ZW50aWFsIHByZWRpY3RvciBkYXRhIGFyZSBwbG90dGVkIGFuZCBhIGNvbWJpbmF0aW9uIG9mIHRoZSBwb3RlbnRpYWwgcHJlZGljdG9ycyBhcmUgY29tYmluZWQuIFRoZXNlIHByZWRpY3RvcnMgYXJlIGFsc28gY29tYmluZWQgd2l0aGluIGFub3RoZXIgZGF0YSBmcmFtZS4KCkFsc28gYSB0aW1lIHNlcmllcyBmb3IgY29yb25hLXN0YXJ0IGR1bW15IHZhcmlhYmxlIGlzIGNyZWF0ZWQKCmBgYHtyfQp0aWNhcmV0ID0gZnJlYWQoIi9Vc2Vycy9haG1ldGthcmFrb3NlL0Rlc2t0b3AvdGljYXJldC5jc3YiKQpuYW1lcyh0aWNhcmV0KVtuYW1lcyh0aWNhcmV0KSA9PSAidGljYXJldDogKFTDvHJraXllKSJdIDwtICJUaWNhcmV0Igp0aWNhcmV0X3RzIDwtIHRzKHRpY2FyZXRbLC0xXSwgc3RhcnQgPSB0aW1lX2RhdGEsIGZyZXF1ZW5jeSA9IDEyKQoKdXJldGltID0gZnJlYWQoIi9Vc2Vycy9haG1ldGthcmFrb3NlL0Rlc2t0b3AvdXJldGltLmNzdiIpCm5hbWVzKHVyZXRpbSlbbmFtZXModXJldGltKSA9PSAiw7xyZXRpbTogKFTDvHJraXllKSJdIDwtICLDnHJldGltIgp1cmV0aW1fdHMgPC0gdHModXJldGltWywtMV0sIHN0YXJ0ID0gdGltZV9kYXRhLCBmcmVxdWVuY3kgPSAxMikKCmlzdGloZGFtID0gZnJlYWQoIi9Vc2Vycy9haG1ldGthcmFrb3NlL0Rlc2t0b3AvaXN0aWhkYW0uY3N2IikKbmFtZXMoaXN0aWhkYW0pW25hbWVzKGlzdGloZGFtKSA9PSAiaXN0aWhkYW06IChUw7xya2l5ZSkiXSA8LSAixLBzdGloZGFtIgppc3RpaGRhbV90cyA8LSB0cyhpc3RpaGRhbVssLTFdLCBzdGFydCA9IHRpbWVfZGF0YSwgZnJlcXVlbmN5ID0gMTIpCgpjb3JvbmFfdmFsdWVzIDwtIHJlcCgwLCAxMjEpCmNvcm9uYV92YWx1ZXNbNzVdIDwtIDEKY29yb25hX3RzIDwtIHRzKGNvcm9uYV92YWx1ZXMsIHN0YXJ0ID0gYygyMDE0LCAxKSwgZnJlcXVlbmN5ID0gMTIpCgphdXRvcGxvdChmYWl6X3RzKQphdXRvcGxvdCh0aWNhcmV0X3RzKQphdXRvcGxvdCh1cmV0aW1fdHMpCmF1dG9wbG90KGlzdGloZGFtX3RzKQphdXRvcGxvdChjb3JvbmFfdHMpCgpwcmVkaWN0b3JzX2NvbmZpZGVuY2UgPC0gY2JpbmQoZmFpelssLTFdLCB0aWNhcmV0WywtMV0sIHVyZXRpbVssLTFdLCBpc3RpaGRhbVssLTFdKQpkZl9jb25maWRlbmNlIDwtIGNiaW5kKGNvbmZpZGVuY2UsIHByZWRpY3RvcnNfY29uZmlkZW5jZSkKCmBgYApCZWxvdyBpcyB0aGUgY29ycmVsYXRpb25zIGJldHdlZW4gZWFjaCBwcmVkaWN0b3JzIGFuZCB0aGUgZm9yZWNhc3QgdmFyaWFibGUuIFRoZSByZWxhdGlvbnMgb2YgZWFjaCBvZiB0aGVtIGNhbiBiZSBvYnNlcnZlZCBiZWxvdy4KYGBge3J9CnJlcXVpcmUoR0dhbGx5KQpnZ3BhaXJzKGRmX2NvbmZpZGVuY2VbLC0xXSkKYGBgCgpXZSB3ZXJlIG5vdCBhYmxlIHRvIGRlY2lkZSB3aGV0aGVyIHNlYXNuYWxpdHkgYW5kIHRyZW5kIHdlcmUgbmVjZXNzYXJ5LiBBcHBhcmVudGx5IHRoZSBhZGp1c3RlZCBSXjIgdmFsdWUgdGVsbHMgdXMgdG8gYWRkIHNlYXNub2FsaXR5IGFuZCB0cmVuZCBhcyBwcmVkaWN0b3JzCmBgYHtyfQpmaXQgPC0gdHNsbShjb25maWRlbmNlX3RzIH4gZmFpel90cyArIAogICAgICAgICAgICAgICAgICAgICAgICB0aWNhcmV0X3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHVyZXRpbV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICBpc3RpaGRhbV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICBjb3JvbmFfdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdCArIAogICAgICAgICAgICAgICAgICAgICAgICBzZWFzb24pCgpmaXQuc2Vhc29uIDwtIHRzbG0oY29uZmlkZW5jZV90cyB+IGZhaXpfdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGljYXJldF90cyArIAogICAgICAgICAgICAgICAgICAgICAgICB1cmV0aW1fdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgaXN0aWhkYW1fdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgY29yb25hX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHNlYXNvbikKCmZpdC50cmVuZCA8LSB0c2xtKGNvbmZpZGVuY2VfdHMgfiBmYWl6X3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRpY2FyZXRfdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdXJldGltX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGlzdGloZGFtX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvcm9uYV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICB0KQpmaXQubm9uZSA8LSB0c2xtKGNvbmZpZGVuY2VfdHMgfiBmYWl6X3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRpY2FyZXRfdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdXJldGltX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGlzdGloZGFtX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvcm9uYV90cykKCm5vX3NlYXNvbl9ub190cmVuZCA8LSBDVihmaXQudHJlbmQpCnNlYXNvbl9ub190cmVuZCA8LSBDVihmaXQuc2Vhc29uKQp0cmVuZF9ub19zZWFzb24gPC0gQ1YoZml0LnRyZW5kKQphbGwgPC0gQ1YoZml0KQpDVl9kYXRhIDwtIGRhdGEuZnJhbWUocmJpbmQobm9fc2Vhc29uX25vX3RyZW5kLCBzZWFzb25fbm9fdHJlbmQsIHRyZW5kX25vX3NlYXNvbiwgYWxsKSkKQ1ZfZGF0YQpgYGAKTm93aSB0aGUgbGFnZ2VkIGRhdGEgZnJhbWVzIGZvciBhbGwgb2YgdGhlIHNlbGVjdGVkIHByZWRpY3RvcnMgYXJlIGNyZWF0ZWQgKEdvb2dsZSB0cmVuZHMgZGF0YSkuIFRoaXMgaXMgdG8gY29tcGFyZSB0aGUgbGFnZ2VkIG1vZGVscyB3aXRob3V0IHRoZSBsYWdnZWQgbW9kZWwuIFRoZW4gdGhlIHBpZWNlIHdpc2UgbGluZWFyIHRyZW5kIGlzIGZvcm1lZC4gVGhyZWUgcG9zc2libGUgbW9kZWxzIGFyZSBjcmVhdGVkOgoKLSAgIGZpdDogVXNpbmcgYWxsIHRoZSBwcmVkaWN0b3JzCi0gICBmaXQubGFnMTogVXNpbmcgYWxsIHRoZSBsYWctMSBwcmVkaWN0b3JzCi0gICBmaXQubGFnMjogVXNpbmcgYWxsIHRoZSBsYWctMiBwcmVkaWN0b3JzCgpUaGUgYmVzdCBvbmUgd2lsbCBiZSBldmFsdWF0ZWQgYmFzZWQgb24gdGhlIGxvd2VzdCBBSUMgdmFsdWUuIEFzIGl0IGNhbiBiZSBzZWVuIGJlbG93LCB0aGUgbG93ZXN0IEFJQyB2YWx1ZSBpcyB0aGUgb25lIHdpdGggbm8gbGFnLiBXZSB3aWxsIHByb2NlZWQgd2l0aCB0aGlzIG1vZGVsIGluIHRoZSB1cGNvbWluZyBjb21wYXJpc29ucy4KYGBge3J9CmxpYnJhcnkoZHBseXIpCgpmYWl6X2xhZyA8LSBtdXRhdGUoZmFpeiwKICAgICAgICAgICAgICAgZmFpel9sYWcxID0gbGFnKGZhaXokRmFpeiwgMSksICAjIExhZyAxCiAgICAgICAgICAgICAgIGZhaXpfbGFnMiA9IGxhZyhmYWl6JEZhaXosIDIpLCAgIyBMYWcgMgogICAgICAgICAgICAgICApCgp0aWNhcmV0X2xhZyA8LSBtdXRhdGUodGljYXJldCwKICAgICAgICAgICAgICAgdGljYXJldF9sYWcxID0gbGFnKHRpY2FyZXQkVGljYXJldCwgMSksICAjIExhZyAxCiAgICAgICAgICAgICAgIHRpY2FyZXRfbGFnMiA9IGxhZyh0aWNhcmV0JFRpY2FyZXQsIDIpLCAgIyBMYWcgMgogICAgICAgICAgICAgICApCgp1cmV0aW1fbGFnIDwtIG11dGF0ZSh1cmV0aW0sCiAgICAgICAgICAgICAgIHVyZXRpbV9sYWcxID0gbGFnKHVyZXRpbSTDnHJldGltLCAxKSwgICMgTGFnIDEKICAgICAgICAgICAgICAgdXJldGltX2xhZzIgPSBsYWcodXJldGltJMOccmV0aW0sIDIpLCAgIyBMYWcgMgogICAgICAgICAgICAgICApCgppc3RpaGRhbV9sYWcgPC0gbXV0YXRlKGlzdGloZGFtLAogICAgICAgICAgICAgICBpc3RpaGRhbV9sYWcxID0gbGFnKGlzdGloZGFtJMSwc3RpaGRhbSwgMSksICAjIExhZyAxCiAgICAgICAgICAgICAgIGlzdGloZGFtX2xhZzIgPSBsYWcoaXN0aWhkYW0kxLBzdGloZGFtLCAyKSwgICMgTGFnIDIKICAgICAgICAgICAgICAgKQoKY29tYmluZWRfbGFnIDwtIGNiaW5kKGZhaXpfbGFnLCB0aWNhcmV0X2xhZywgdXJldGltX2xhZywgaXN0aWhkYW1fbGFnKQoKZml0IDwtIHRzbG0oY29uZmlkZW5jZV90cyB+IGZhaXpfdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGljYXJldF90cyArIAogICAgICAgICAgICAgICAgICAgICAgICB1cmV0aW1fdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgaXN0aWhkYW1fdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgY29yb25hX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHQgKyAKICAgICAgICAgICAgICAgICAgICAgICAgc2Vhc29uKQoKZml0LmxhZzEgPC0gdHNsbShjb25maWRlbmNlX3RzIH4gdCArIAogICAgICAgICAgICAgICAgICAgICAgICBzZWFzb24gKyAKICAgICAgICAgICAgICAgICAgICAgICAgZmFpel9sYWcxICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRpY2FyZXRfbGFnMSArIAogICAgICAgICAgICAgICAgICAgICAgICB1cmV0aW1fbGFnMSArIAogICAgICAgICAgICAgICAgICAgICAgICBpc3RpaGRhbV9sYWcxLCBkYXRhID0gY29tYmluZWRfbGFnKQoKZml0LmxhZzIgPC0gdHNsbShjb25maWRlbmNlX3RzIH4gdCArIAogICAgICAgICAgICAgICAgICAgICAgICBzZWFzb24gKyAKICAgICAgICAgICAgICAgICAgICAgICAgZmFpel9sYWcyICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHRpY2FyZXRfbGFnMiArIAogICAgICAgICAgICAgICAgICAgICAgICB1cmV0aW1fbGFnMiArIAogICAgICAgICAgICAgICAgICAgICAgICBpc3RpaGRhbV9sYWcyLCBkYXRhID0gY29tYmluZWRfbGFnKQoKbm9fbGFnIDwtIENWKGZpdCkKbGFnXzEgPC0gQ1YoZml0LmxhZzEpCmxhZ18yIDwtIENWKGZpdC5sYWcyKQpDVl9kYXRhIDwtIGRhdGEuZnJhbWUocmJpbmQobm9fbGFnLCBsYWdfMSwgbGFnXzIpKQpDVl9kYXRhCmBgYApOb3csIHdlIHdpbGwgaW5zcGVjdCB0aGUgbW9kZWwgZnVydGhlciBhbmQgdHJ5IHRvIHJlbW92ZSB0aGUgdW5uZWNlc3NhcnkgcHJlZGljdG9yLiBJbiB0aGlzIGNhc2UgYWxsIG9mIHRoZSBwcmVkaWN0b3JzIChHb29nbGUgdHJlbmRzIGRhdGEpIGFyZSByZW1vdmVkIG9uZSBieSBvbmUgYW5kIHRoZSBtb2RlbHMgYXJlIGNvbXBhcmVkIGFjY29yZGluZyB0byBBSUMgYW5kIGFkai4gUl4yIHZhbHVlcy4gVGhlIGJlc3QgbW9kZWxzIGFyZSBmaXQuZXZlcnl0aGluZyBhbmQgZml0Lncuby5jb3JvbmEgcmVzcGVjdGl2ZWx5IGZvciBhZGouIFJeMiB2YWx1ZSBhbmQgQUlDIHZhbHVlLiBXZSB3aWxsIHByb2NlZWQgd2l0aCBmaXQuZXZlcnl0aGluZwpgYGB7cn0KZml0LmV2ZXJ5dGhpbmcgPC0gdHNsbShjb25maWRlbmNlX3RzIH4gZmFpel90cyArIAogICAgICAgICAgICAgICAgICAgICAgICB0aWNhcmV0X3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHVyZXRpbV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICBpc3RpaGRhbV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICBjb3JvbmFfdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdCArIAogICAgICAgICAgICAgICAgICAgICAgICBzZWFzb24pCgpmaXQudy5vLmZhaXogPC0gdHNsbShjb25maWRlbmNlX3RzIH4gdGljYXJldF90cyArIAogICAgICAgICAgICAgICAgICAgICAgICB1cmV0aW1fdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgaXN0aWhkYW1fdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgY29yb25hX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHQgKyAKICAgICAgICAgICAgICAgICAgICAgICAgc2Vhc29uKQoKZml0Lncuby50aWNhcmV0IDwtIHRzbG0oY29uZmlkZW5jZV90cyB+IGZhaXpfdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdXJldGltX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGlzdGloZGFtX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvcm9uYV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICB0ICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHNlYXNvbikKCmZpdC53Lm8udXJldGltIDwtIHRzbG0oY29uZmlkZW5jZV90cyB+IGZhaXpfdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGljYXJldF90cyArIAogICAgICAgICAgICAgICAgICAgICAgICBpc3RpaGRhbV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICBjb3JvbmFfdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdCArIAogICAgICAgICAgICAgICAgICAgICAgICBzZWFzb24pCgpmaXQudy5vLmlzdGloZGFtIDwtIHRzbG0oY29uZmlkZW5jZV90cyB+IGZhaXpfdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgdGljYXJldF90cyArIAogICAgICAgICAgICAgICAgICAgICAgICB1cmV0aW1fdHMgKyAKICAgICAgICAgICAgICAgICAgICAgICAgY29yb25hX3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHQgKyAKICAgICAgICAgICAgICAgICAgICAgICAgc2Vhc29uKQoKZml0Lncuby5jb3JvbmEgPC0gdHNsbShjb25maWRlbmNlX3RzIH4gZmFpel90cyArIAogICAgICAgICAgICAgICAgICAgICAgICB0aWNhcmV0X3RzICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHVyZXRpbV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICBpc3RpaGRhbV90cyArIAogICAgICAgICAgICAgICAgICAgICAgICB0ICsgCiAgICAgICAgICAgICAgICAgICAgICAgIHNlYXNvbikKCmFsbCA8LSBDVihmaXQuZXZlcnl0aGluZykKbm9fZmFpeiA8LSBDVihmaXQudy5vLmZhaXopCm5vX3RpY2FyZXQgPC0gQ1YoZml0Lncuby50aWNhcmV0KQpub191cmV0aW0gPC0gQ1YoZml0Lncuby51cmV0aW0pCm5vX2lzdGloZGFtIDwtIENWKGZpdC53Lm8uaXN0aWhkYW0pCm5vX2Nvcm9uYSA8LSBDVihmaXQudy5vLmNvcm9uYSkKQ1ZfZGF0YSA8LSBkYXRhLmZyYW1lKHJiaW5kKGFsbCwgbm9fZmFpeiwgbm9fdGljYXJldCwgbm9fdXJldGltLCBub19pc3RpaGRhbSwgbm9fY29yb25hKSkKQ1ZfZGF0YQpgYGAKVGhlIG1vZGVsIGFuZCB0aGUgZGF0YSBhcmUgcGxvdHRlZCBpbiBvcmRlciB0byBzZWUgdmlzdWFsbHkgaG93IHRoZXkgYmVoYXZlLgoKYGBge3J9CmF1dG9wbG90KGNvbmZpZGVuY2VfdHMsIHNlcmllcyA9ICJEYXRhIikgKyAKICBhdXRvbGF5ZXIoZml0dGVkKGZpdC5ldmVyeXRoaW5nKSwgc2VyaWVzID0gIk1vZGVsIikKYGBgCkZyb20gdGhlIHJlc2lkdWFsIGFuYWx5c2lzIHBhcnQgd2UgY2FuIGNvbmNsdWRlIHRoYXQ6CgotICAgVGhlIHJlc2lkdWFscyBzZWVtIHRvIGhhdmUgbWVhbiB6ZXJvIGFuZCB0aGVtIHNlZW0gdG8gYmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuCi0gICBIb3dldmVyIHRoZSBkYXRhIHNob3cgdmVyeSBoaWdoIGF1dG9jb3JyZWxhdGlvbiBiZXR3ZWVuIHJlc2lkdWFscy4KCldoZW4gY29uc2lkZXJpbmcgZGlmZmVyZW50IHByZWRpY3RvcnMgd2UgY2FuIG9ic2VydmUgdGhhdCBtb3N0IG9mIHRoZSBzZWFzb25hbGl0eSB2YWx1ZXMgYXJlIG5vdCB0aGF0IGluZm9ybWF0aXZlIChXZSB3ZXJlIG5vdCBzdXJlIHdoZXRoZXIgdG8gYWRkIHRvIHRoZSBtb2RlbCkKCldoZW4gdGhlIFJlc2lkdWFscyB2cy4gRml0dGVkIHZhbHVlcyBncmFwaCBpcyBvYnNlcnZlZCwgaXQgY2FuIGJlIHNlZW4gdGhhdCB0aGUgcmVzaWR1YWxzIGFyZSBraW5kIG9mIHNjYXR0ZXJlZCBhcm91bmQgCgpPdmVyYWxsLCB0aGUgbW9kZWwgc2VlbXMgdG8gZGVvc24ndCBzZWVtIGFkZXF1YXRlIGFzIHRoZXJlIGlzIHJlYWxseSBoaWdoIEFDIGJldHdlZW4gcmVzaWR1YWxzIGFuZCB0aGUgYWRqdXN0ZWQgUl4yIHZhbHVlIGlzIHByZXR0eSBzbWFsbC4KCmBgYHtyfQpzdW1tYXJ5KGZpdC5ldmVyeXRoaW5nKQpjaGVja3Jlc2lkdWFscyhmaXQuZXZlcnl0aGluZykKCnJlc2lkdWFsX2ZpdHRlZCA8LSBkYXRhLmZyYW1lKGNiaW5kKEZpdHRlZCA9IGZpdHRlZChmaXQuZXZlcnl0aGluZyksIFJlc2lkdWFscz1yZXNpZHVhbHMoZml0LmV2ZXJ5dGhpbmcpKSkKZ2dwbG90KHJlc2lkdWFsX2ZpdHRlZCwgYWVzKHggPSBGaXR0ZWQsIHkgPSBSZXNpZHVhbHMpKSArIGdlb21fcG9pbnQoKSArIGdndGl0bGUoIlJlc2lkdWFscyB2cy4gRml0dGVkIFZhbHVlcyIpCmBgYAojIyBDb25jbHVzaW9uCgpPdmVyYWxsLCB3ZSBoYXZlIGJ1aWx0IHRocmVlIHJlZ3Jlc3Npb24gbW9kZWxzIGluIHRocmVlIGRpZmZlcmVudCB0aW1lIHNlcmllcy4gRXZlbiB0aG91Z2ggc29tZSBvZiB0aGUgbW9kZWxzIHdlcmUgYmV0dGVyIHRoYW4gdGhlIG90aGVyIG1vZGVscyB0aGVyZSB3YXMgb25lIGNvbW1vbiBwcm9ibGVtOiBhdXRvY29ycmVsYXRpb24gYmV0d2VlbiByZXNpZHVhbHMuIEluIGFsbCBvZiB0aGUgbW9kZWxzIHRoZSBBQ0YgZ3JhcGggd2FzIG5vdCBhcyBkZXNpcmVkIGFuZCB0aGlzIHJlbWFya2VkIGZ1cnRoZXIgaW52ZXN0aWdhdGlvbiBvbiB0aGUgbW9kZWwuCgpIb3dldmVyIG90aGVyIHRoYW4gdGhpcywgdGhpcyBhc3NpZ25tZW50IHRvdWdodCBob3cgdG8gYnVpbGQgbW9kZWxzLCBzZWxlY3QgcHJlZGljdG9ycywgY29tcGFyZSBtb2RlbHMgYW5kIGRvIHJlc2lkdWFsIGFuYWx5c2lzIGZvciBkaWZmZXJlbnQgdGltZSBzZXJpZXMgYW5kIHdhcyBiZW5lZml0YXJ5LgoKIyMgQXBwZW5kaWNlcwoKQ2hhdEdQVDoKCi0gSGVscCBmcm9tIExMTSBpbiBvcmRlciB0byBjcmVhdGUgZGF0YWZyYW1lcyBhZGQgYW5kIHN1YnRyYWN0IGNvbHVtbnMgYW5kIHJvd3MgYW5kIGFsc28gZm9yIGNyZWF0aW5nIGxhZ2dlZCBkYXRhLg==